我的印象是文件对象在引用计数达到0时立即关闭,因此该行:
foo = open('foo').read()
Run Code Online (Sandbox Code Playgroud)
会得到文件的内容并立即关闭文件.但是,在Python文件对象上使用迭代器时,在读取了Is close()的答案之后,我得到的印象是这不会发生,并且始终需要调用.close()文件对象.
上面的那行是否符合我的想法,即使它确实如此,它是Pythonic要做的吗?
Tom*_*icz 31
答案在您提供的链接中.
垃圾收集器在销毁文件对象时会关闭文件,但是:
你真的无法控制它何时发生.
虽然CPython使用引用计数来确定性地释放资源(因此您可以预测对象何时将被销毁),而其他版本则不需要.例如,Jython或IronPython都使用JVM和.NET垃圾收集器,它只在需要恢复内存时释放(并最终确定)对象,并且在程序结束之前可能不会对某些对象执行此操作.即使对于CPython,GC算法在未来可能会发生变化,因为引用计数效率不高.
如果在文件对象销毁时关闭文件时抛出异常,你就无法对它做任何事情,因为你不会知道.
hug*_*own 27
如果你想确定,我会写这样的代码:
from __future__ import with_statement
with open('foo') as f:
foo = f.read()
Run Code Online (Sandbox Code Playgroud)
这样,即使有例外,您的文件也会按预期关闭.
很久以后:这里有一些代码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
Run Code Online (Sandbox Code Playgroud)
Edw*_*per 10
对于python的cpython实现:是的,它保证在引用计数变为零时关闭.
对于python作为抽象语言(例如,包括Jython,IronPython等):不,它不能保证关闭.特别是,Python的实现可能选择不使用引用计数,而是使用其他形式的GC.
参考文献:
| 归档时间: |
|
| 查看次数: |
19943 次 |
| 最近记录: |