web-dev-qa-db-ja.com

明示的にファイルを閉じることは重要ですか?

Pythonでは、close()を呼び出さずにファイルを開くか、try-_finallyまたは "with"ステートメントを使用せずにファイルを閉じると、これが問題になります?または、すべてのファイルを閉じるためにPythonガベージコレクションに依存することは、コーディングの慣行としては十分ですか?たとえば、これを行う場合:

for line in open("filename"):
    # ... do stuff ...

...ファイルを閉じることができず、ファイルを閉じることができない例外が発生する可能性があるため、これは問題ですか?または、ファイルがスコープ外になるため、forステートメントの終了時に確実に閉じられますか?

136
user553702

この例では、インタープリターが終了する前にファイルが閉じられるとは限りません。現在のバージョンのCPythonでは、CPythonは参照カウントを主要なガベージコレクションメカニズムとして使用しますが、それは言語の機能ではなく実装の詳細であるため、ファイルはforループの終わりで閉じられます。 Pythonの他の実装は、この方法での動作が保証されていません。たとえば、IronPython、PyPy、およびJythonは参照カウントを使用しないため、ループの最後でファイルを閉じません。

コードの移植性が低下するため、CPythonのガベージコレクションの実装に依存するのは悪い習慣です。 CPythonを使用する場合、リソースリークは発生しない可能性がありますが、参照カウントを使用しないPython実装に切り替える場合は、すべてのコードを調べて、すべてのファイルを確認する必要があります。適切に閉じた。

あなたの例では:

with open("filename") as f:
     for line in f:
        # ... do stuff ...
118
Peter Graham

参照されなくなったファイルを自動的に閉じるPythonもありますが、そうでないものもあり、Pythonインタープリターが終了したときにファイルを閉じるのはO/S次第です。

あなたのためにファイルを閉じるPythonでさえ、タイミングは保証されていません:それは即座であるかもしれませんし、数秒/分/時間/日後であるかもしれません。

そのため、使用しているPythonで問題は発生しないかもしれませんが、ファイルを開いたままにしておくことは絶対に良い習慣ではありません。実際、cpython 3では、システムがファイルを閉じなかった場合、ファイルを閉じる必要があるという警告が表示されます。

道徳:自分の後にクリーンアップ。 :)

22
Ethan Furman

この特定のケースでそのような構造を使用することは非常に安全ですが、そのような慣行を一般化するためのいくつかの注意事項があります。

  • runはファイル記述子を使い果たす可能性がありますが、可能性は低いですが、そのようなバグを探すことを想像してください
  • 一部のシステムでは、上記のファイルを削除できない場合があります。 win32
  • cPython以外を実行する場合、ファイルがいつ閉じられるかわかりません
  • ファイルを書き込みモードまたは読み取り/書き込みモードで開いた場合、データがフラッシュされるタイミングはわかりません
9
Dima Tisnek

こんにちは同じpythonスクリプトでコンテンツを使用する場合は、ファイル記述子を閉じることが非常に重要です。私は今日、非常に長い時間をかけてデバッグを行っていました。理由は、ファイル記述子を閉じて、変更がファイルに影響を与えた後にのみコンテンツが編集/削除/保存されるからです!

したがって、新しいファイルにコンテンツを書き込み、fdを閉じずに、そのファイル(fdではなく)をそのコンテンツを読み取る別のシェルコマンドで使用している状況があるとします。この状況では、シェルコマンドの内容が期待どおりに取得されず、デバッグしようとしても、バグを簡単に見つけることができません。また、私のブログエントリで詳細を読むことができます http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html

3
Zeel Shah

ファイルはガベージコレクションされ、閉じられます。 GCは、ユーザーではなく、いつ閉じられるかを決定します。明らかに、ファイルを使い終わったらすぐにファイルを閉じないと、開いているファイルハンドルの制限に達する可能性があるため、これは推奨される方法ではありません。あなたのforループ内で、さらにファイルを開いて、それらを残しておくとどうなりますか?

3
Nam Nguyen

I/Oプロセス中、データはバッファリングされます。つまり、データはファイルに書き込まれる前に一時的な場所に保持されます。

Pythonは、書き込みが完了するまで、バッファをフラッシュしません(つまり、ファイルにデータを書き込みます)。これを行う1つの方法は、ファイルを閉じることです。

閉じずにファイルに書き込むと、データはターゲットファイルに到達しません。

1
Sanket Nagrale