在python中打开的文件描述符

在python中打开的文件描述符,python,file,python-3.x,Python,File,Python 3.x,当我在IPython3 shell中使用此代码时 >>>data = open('file').read() 然后检查打开的文件描述符: lsof | grep file 我发现空名单 当我使用这个时: >>>open('file') lsof显示两个项目。问题是为什么第一个操作关闭fd而第二个操作不关闭?我认为垃圾收集器必须删除没有引用的文件对象 当我重新赋值时,我知道解释器中的“uvar” >>>111 >>>

当我在IPython3 shell中使用此代码时

 >>>data = open('file').read()
然后检查打开的文件描述符:

 lsof | grep file
我发现空名单

当我使用这个时:

>>>open('file')
lsof
显示两个项目。问题是为什么第一个操作关闭fd而第二个操作不关闭?我认为垃圾收集器必须删除没有引用的文件对象

当我重新赋值时,我知道解释器中的“uvar”

>>>111
>>>_
111
但描述符仍然是开放的。 当我重复的时候

>>>open('file')

n次有2*n个打开的描述符

默认Python实现同时使用垃圾收集和引用计数。在第一个示例中,文件对象的引用计数降至零,因此即使在垃圾收集器运行之前,它也会立即关闭

第二个版本与此等效:

_ = open('file')
由于文件仍由
引用,因此在运行另一个命令之前,该文件仍处于活动状态

请注意,此行为特定于CPython。其他实现(如IronPython)关闭文件的速度可能不会太快,因此您应该在使用完文件后真正关闭它们。一个很好的方法是使用一个

相关的


在第二个示例中,文件句柄由交互式解释器变量
保留,该变量允许您访问最后计算的表达式。如果计算另一个表达式,如
1+1
,您将注意到
lsof
不再将该文件报告为打开

正如Mike Byers所指出的,这种行为是特定于CPython的,甚至是特定于如何使用file对象的精确环境。要确保无论代码如何执行,文件都已关闭,请使用
with
语句:

with open('file') as fp:
    data = fp.read()

这是因为您正在使用的交互式解释器保留对最后返回的对象的隐式引用。该引用名为

Python2> open("/etc/hosts") 
<open file '/etc/hosts', mode 'r' at 0xf2c390> 
Python2> _ 
<open file '/etc/hosts', mode 'r' at 0xf2c390>
文件现在已关闭,因为它不再被引用


但这是一个很好的例子,说明了为什么您应该显式关闭您真正想要关闭的文件。

如果我重复打开(“文件”)n次,将打开2*n个文件descriptors@adray你是怎么得出这个结论的?对
open
的一次调用应该对应于一个打开的文件描述符。@adray我不能用Python 2.7.3重复这一点;请看我在问题下的评论。@adray你能给我们举个例子吗?我也没有看到,这里要补充的是,在第一个实例中,文件描述符对象没有返回,文件的内容是。由于python的解释器允许您通过
>>\uuu
获取最后一个命令的结果,因此第二个实例仍然具有对可用文件描述符的引用。您使用的是哪个python shell?在默认的Python shell中,在Python 2.7.3中,只要输入第二个表达式,即重新分配
\uu
的表达式,就会释放文件描述符;但是,我也不能在Python3.3.0中重复这一点。我执行
open('somefile')
,在另一个shell中
lsof
显示要打开的文件。然后我执行
1+1
,在shell中
lsof
显示不打开的文件。
Python2> open("/etc/hosts") 
<open file '/etc/hosts', mode 'r' at 0xf2c390> 
Python2> _ 
<open file '/etc/hosts', mode 'r' at 0xf2c390>
Python2> max(0,1)
1