回答:
その質問への答えは、特定の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#objects-values-and-types
(エンファシス鉱山)
しかし、それが示唆するように、他の実装には他の振る舞いがあるかもしれません。例として、PyPyには6つの異なるガベージコレクションの実装があります。
__exit__()
そのような場合に呼び出さないことは、設計上の欠陥のように聞こえます。
try
/ finally
手ごわい、非常に一般的な役に立たないクリーンアップハンドラーがwith
解決します。「明示的に閉じる」と「で管理するwith
」の違いは、例外がスローされても出口ハンドラーが呼び出されることです。あなたは置くことができるclose()
にfinally
句が、それはあまり使用して異なるではないwith
代わりに、ビットメシエ(3つの余分な行の代わりに、1)、そして少し難しくちょうど権利を取得します。
with foo() as f: [...]
基本的に同じでf = foo()
、例外が処理されるため、より信頼性が高く、常に呼び出されます。したがって、ファイルは常に閉じられます。f.__enter__()
f.__exit__()
__exit__
pathlibを使用できます。
Python 3.5以降の場合:
from pathlib import Path
contents = Path(file_path).read_text()
古いバージョンのPythonでは、pathlib2を使用します。
$ pip install pathlib2
次に:
from pathlib2 import Path
contents = Path(file_path).read_text()
これは実際のread_text
実装です:
def read_text(self, encoding=None, errors=None):
"""
Open the file in text mode, read it, and close the file.
"""
with self.open(mode='r', encoding=encoding, errors=errors) as f:
return f.read()
ファイルのコンテンツを単一の文字列として取得する代わりに、ファイルを構成するすべての行のリストとしてコンテンツを保存すると便利です。
with open('Path/to/file', 'r') as content_file:
content_list = content_file.read().strip().split("\n")
ご覧のとおり、このスレッドのメインの回答に連結されたメソッド.strip().split("\n")
を追加する必要があります。
ここ.strip()
では、ファイル文字列全体の末尾にある空白文字と改行文字を削除.split("\n")
し、改行文字 \ nごとにファイル文字列全体を分割して実際のリストを生成します。
さらに、この方法では、前の回答で指摘したようにファイルを1行ずつループする代わりに、ファイルコンテンツ全体を変数に格納できます。