ファイル全体を読み取る場合、content = open('Path/to/file', 'r').read()
スクリプトが終了するまでファイル ハンドルは開いたままになりますか? ファイル全体を読み取るより簡潔な方法はありますか?
ベストアンサー1
この質問に対する答えは、特定の Python 実装によって多少異なります。
これが何を意味するのかを理解するには、実際のfile
オブジェクトに特に注意してください。コードでは、そのオブジェクトは式の中で 1 回だけ言及され、呼び出しが返されるとすぐにアクセスできなくなりますread()
。
これは、ファイル オブジェクトがガベージであることを意味します。残る唯一の疑問は、「ガベージ コレクターはいつファイル オブジェクトを収集するのか?」です。
参照カウンタを使用する CPython では、この種のガベージはすぐに認識され、すぐに収集されます。これは、他の Python 実装では一般的に当てはまりません。
ファイルが閉じられていることを確認するためのより良い解決策は、次のパターンです。
with open('Path/to/file', 'r') as content_file:
content = content_file.read()
例外が発生した場合でも、ブロックが終了するとすぐにファイルを閉じます。
編集: もう少し詳しく説明すると:
file.__exit__()
コンテキスト マネージャー設定で「自動的に」呼び出される以外ではwith
、 が自動的に呼び出される唯一の方法file.close()
(つまり、自分で明示的に呼び出す以外) は を使用することです。ここで、 がいつ呼び出されるかfile.__del__()
という疑問が生じます。__del__()
正しく記述されたプログラムでは、プログラム終了前のどの時点でもファイナライザが実行されるとは想定できません。
--https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203
特に:
オブジェクトが明示的に破棄されることはありませんが、オブジェクトが到達不能になった場合はガベージ コレクションされる可能性があります。実装では、ガベージ コレクションを延期したり、完全に省略したりできます。まだ到達可能なオブジェクトが収集されない限り、ガベージ コレクションがどのように実装されるかは実装品質の問題です。
[...]
CPython は現在、循環的にリンクされたガベージの遅延検出 (オプション) を備えた参照カウント スキームを使用しており、ほとんどのオブジェクトは到達不能になるとすぐに収集されますが、循環参照を含むガベージが収集される保証はありません。
--https://docs.python.org/3.5/reference/datamodel.html#オブジェクト値とタイプ
(強調は筆者による)
しかし、他の実装では異なる動作をする可能性がある。例として、PyPy6つの異なるガベージコレクション実装がある!