我的印象是文件对象在引用计数达到0时立即关闭,因此行:
foo = open('foo').read()
会获取文件的内容并立即关闭文件。但是,在阅读Is close() necessary when using iterator on a Python file object的答案后,我得到的印象是,这种情况不会发生,并且在文件对象上调用.close()
总是是必要的。
上面的那行是否按照我的想法行事,即使它确实如此,它是Pythonic要做的吗?
答案 0 :(得分:30)
答案在您提供的链接中。
垃圾收集器在销毁文件对象时会关闭文件,但是:
你真的无法控制它何时发生。
虽然CPython使用引用计数来确定性地释放资源 (因此您可以预测何时销毁对象)其他版本不必。 例如,Jython或IronPython都使用JVM和.NET垃圾收集器 仅在需要恢复内存时才释放(并完成)对象 并且在程序结束之前可能不会为某个对象执行此操作。 甚至对于CPython GC算法可能在将来作为引用计数而改变 效率不高。
如果在文件对象销毁时关闭文件时抛出异常, 你不能真正做任何事情,因为你不会知道。
答案 1 :(得分:27)
如果你想确定,我会编写如下代码:
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
答案 2 :(得分:10)
对于python的cpython实现:是的,保证在引用计数为零时关闭。
对于python作为抽象语言(例如,包括Jython,IronPython等):不,不保证关闭它。特别是,Python的实现可能选择不使用引用计数,而是使用其他形式的GC。
<强>参考文献:强>
答案 3 :(得分:1)
不,Python优化删除未使用的对象,因此它可能永远不会关闭您的文件(在退出时脚本结束时确定它将清理)。 @ hughdbrown指出了很好的解决方案。