web-dev-qa-db-ja.com

参照カウントがゼロに達すると、ファイルオブジェクトは自動的に閉じますか?

参照カウントが0に達すると、ファイルオブジェクトはすぐに閉じられるという印象を受けました。したがって、次の行になります。

_foo = open('foo').read()
_

ファイルの内容を取得し、すぐにファイルを閉じます。ただし、 Pythonファイルオブジェクト でイテレータを使用する場合はclose()が必要です] ==の答えを読んだ後、これは発生せず、.close()を呼び出すという印象を受けます。ファイルオブジェクトには常に必要です。

上記の行は、私が考えていることを実行していますか?実行している場合でも、Pythonのように実行していますか?

38
Brent Newey

答えはあなたが提供したリンクにあります。

ガベージコレクターは、ファイルオブジェクトを破棄するとファイルを閉じますが、次のようになります。

  • いつ発生するかを実際に制御することはできません。

    CPythonは参照カウントを使用してリソースを決定論的に解放しますが(オブジェクトがいつ破棄されるかを予測できるため)、他のバージョンではそうする必要はありません。たとえば、JythonとIronPythonはどちらも、JVMと.NETガベージコレクターを使用します。これらは、メモリを回復する必要がある場合にのみオブジェクトを解放(およびファイナライズ)し、プログラムが終了するまで一部のオブジェクトに対してそれを行わない場合があります。また、CPythonの場合でも、参照カウントはあまり効率的ではないため、GCアルゴリズムは将来変更される可能性があります。

  • ファイルオブジェクトの破棄時にファイルを閉じるときに例外がスローされた場合、分からないため、実際には何もできません。

31

確認したい場合は、次のようなコードを記述します。

from __future__ import with_statement

with open('foo') as f:
    foo = f.read()

そうすれば、例外があっても、ファイルは期待どおりに閉じます。


ずっと後:コンパイラがこれらをどのように異なる方法で処理するかを示すために、import disを含むコードを次に示します。

>>> def foo(filename):
...     with open(filename) as f:
...         return f.read()
... 
>>> def bar(filename):
...     return open(filename).read()
... 
>>> from dis import dis
>>> 
>>> dis(foo)
  2           0 LOAD_GLOBAL              0 (open)
              3 LOAD_FAST                0 (filename)
              6 CALL_FUNCTION            1
              9 DUP_TOP             
             10 LOAD_ATTR                1 (__exit__)
             13 ROT_TWO             
             14 LOAD_ATTR                2 (__enter__)
             17 CALL_FUNCTION            0
             20 STORE_FAST               1 (_[1])
             23 SETUP_FINALLY           23 (to 49)
             26 LOAD_FAST                1 (_[1])
             29 DELETE_FAST              1 (_[1])
             32 STORE_FAST               2 (f)

  3          35 LOAD_FAST                2 (f)
             38 LOAD_ATTR                3 (read)
             41 CALL_FUNCTION            0
             44 RETURN_VALUE        
             45 POP_BLOCK           
             46 LOAD_CONST               0 (None)
        >>   49 WITH_CLEANUP        
             50 END_FINALLY         
             51 LOAD_CONST               0 (None)
             54 RETURN_VALUE        
>>> dis(bar)
  2           0 LOAD_GLOBAL              0 (open)
              3 LOAD_FAST                0 (filename)
              6 CALL_FUNCTION            1
              9 LOAD_ATTR                1 (read)
             12 CALL_FUNCTION            0
             15 RETURN_VALUE 
27
hughdbrown

pythonのcpython実装の場合:はい、参照カウントがゼロになったときに閉じられることが保証されています。

抽象言語としてのpython(Jython、IronPythonなどを含む)の場合:いいえ、保証されません特に、Pythonの実装では、参照カウントを使用せずに、他の形式のGCを使用することを選択できます。

参考文献:

11
Edward Loper

いいえ、Python未使用のオブジェクトの削除を最適化してファイルを閉じないようにします(スクリプトの最後で終了時にOKでクリーンアップされます)。@ hughdbrownがニースのソリューションを指摘しました。

1
przemo_li