2

pickleモジュールのドキュメントには、サンプルコードのスニペットがあります。

reader = pickle.load(open('save.p', 'rb'))

これは、最初に読み取ると、システムファイル記述子を割り当て、その内容を読み取り、開いている記述子を「リーク」するように見えました。これは、呼び出すためにアクセスできるハンドルがないためclose()です。これは、このケースを処理する隠された魔法があるかどうか疑問に思いました。

ソースを調べてみると、Modules / _fileio.cで、ファイル記述子がfileio_dealloc()デストラクタによって閉じられていることがわかりました。これが実際の質問につながりました。

上記のサンプルコードで使用されているファイルオブジェクトの期間はどのくらいですか?そのステートメントが実行された後、オブジェクトは実際に参照されなくなりますか?したがって、fdはclose(2)将来のガベージコレクションスイープで実際の呼び出しの対象になりますか?もしそうなら、例の行は良い習慣ですか、それともfdがリリースされることを期待してはいけないので、カーネルのプロセスごとの記述子テーブルが使い果たされる危険がありますか?

4

1 に答える 1

3

上記のサンプルコードによって返されるファイルオブジェクトの期間はどのくらいですか?

そのコードはファイルオブジェクトを返しません(Qのタイトルが正しく言うように、引数として受け取ります)。

現在のCPythonでは、関数が戻るときにファイルが閉じられます(関数は、ファイルオブジェクトへの参照をより耐久性のある場所に隠さないため)。他の実装では、ファイルは「最終的に」閉じられますが、正確な時刻は指定されていません。

CPythonの即時閉鎖セマンティクス(将来のCPythonがより優れたガベージコレクションメカニズムに移行すると変更される可能性があります)に応じて、非常に従来のアプローチではありますが、ベストプラクティスではありません。

むしろ、ベストプラクティスは次のwithステートメントを使用することです。

with open(...) as f:
  reader = pickle.load(f)

この使用によりwith、すべての実装でファイルの即時クローズ(ステートメントの本文が終了するとすぐに)が保証されます。

from __future__ import with_statementPython 2.5では、を使用する必要があることに注意してくださいwith。2.6以降では、このような「将来からのインポート」はこの目的には必要ありません(無害ですが、2.5で実行する予定がないことがわかっている場合は、冗長であり、削除する方が適切です)。

于 2010-03-23T01:42:22.513 に答える