1. ホーム
  2. python

[解決済み] ファイル全体を読み込むと、ファイルハンドルが開いたままになりますか?

2022-03-24 18:09:26

質問

を使用してファイル全体を読み込むと content = open('Path/to/file', 'r').read() は、スクリプトが終了するまでファイルハンドルを開いたままにするのでしょうか? もっと簡潔にファイル全体を読み取る方法はないのでしょうか?

どのように解決するのですか?

その答えは、特定のPythonの実装に多少依存します。

これがどういうことかを理解するために、特に実際の file オブジェクトを作成します。 あなたのコードでは、このオブジェクトは式の中で一度だけ言及され、その直後にはアクセスできなくなります。 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 ガベージコレクションの実装が異なる !