当一个文件对象的引用计数为零时,它会自动关闭吗?

2024-06-16 13:33:46 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的印象中,当文件对象的引用计数达到0时,它们会立即关闭,因此行:

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

会得到文件的内容并立即关闭文件。然而,在阅读了对Is close() necessary when using iterator on a Python file object的答案之后,我得到的印象是,这不会发生,并且对文件对象调用.close()始终是必需的。

上面这条线是不是做了我认为它在做的事情,即使它做了,这是不是Python的事情?


Tags: 文件对象内容closereadfooisopen
3条回答

对于python的cpython实现:是,当它的引用计数变为零时,它保证关闭。

对于作为抽象语言的python(例如,包括Jython、IronPython等):不,不保证它是关闭的。特别是,Python的实现可以选择不使用引用计数,而是使用其他形式的GC。

参考资料:

答案在你提供的链接中。

垃圾收集器在销毁文件对象时将关闭文件,但是:

  • 你真的无法控制事情的发生。

    而CPython使用引用计数来确定地释放资源 (所以您可以预测对象何时被销毁)其他版本不必。 例如,Jython或IronPython都使用JVM和.NET垃圾收集器 仅当需要恢复内存时才释放(和完成)对象 在程序结束之前可能不会对某个对象执行此操作。 甚至对于CPython,GC算法在将来也可能作为引用计数而改变 效率不高。

  • 如果在关闭文件对文件对象销毁时引发异常, 你真的什么都做不了,因为你不知道。

如果你想确定,我会这样写代码:

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 

相关问题 更多 >