为了账号安全,请及时绑定邮箱和手机立即绑定

文件对象的引用计数为零时是否自动关闭?

/ 猿问

文件对象的引用计数为零时是否自动关闭?

一只斗牛犬 2019-10-21 15:27:32

我的印象是,当文件对象的引用计数达到0时,文件对象立即关闭,因此该行:


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

会为您获取文件的内容并立即关闭文件。但是,在对Python文件对象使用迭代器时,在阅读了对is close()的回答是必要的之后,我得到的印象是这不会发生,并且始终需要.close()对文件对象进行调用。


上面的代码行是否做了我认为正在做的事情,即使这样做了,这也是Python要做的事情吗?


查看完整描述

3 回答

?
MMMHUHU

答案在您提供的链接中。

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

  • 您真的无法控制何时发生。

    尽管CPython使用引用计数确定性地释放资源(以便您可以预测对象何时被销毁),但其他版本则不需要。例如,Jython或IronPython都使用JVM和.NET垃圾收集器,它们仅在需要恢复内存时才释放(并最终确定)对象,并且可能直到程序结束时才对某些对象执行此操作。甚至对于CPython GC算法,将来也可能会更改,因为引用计数不是很有效。

  • 如果关闭文件对象销毁文件时抛出异常,您将无法做任何事情,因为您将不知道。


查看完整回答
反对 回复 2019-10-21
?
呼如林

如果您想确定的话,可以这样编写代码:


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 


查看完整回答
反对 回复 2019-10-21
?
翻过高山走不出你

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


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


参考文献:


http://docs.python.org/c-api/typeobj.html#tp_dealloc

http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/


查看完整回答
反对 回复 2019-10-21

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信