在pickle module documentation中有一段示例代码:
reader = pickle.load(open('save.p', 'rb'))
在第一次读取时看起来它会分配一个系统文件描述符,读取它的内容,然后“泄漏”打开的描述符,因为没有任何句柄可以访问close()
。这让我想知道是否有任何隐藏的魔法可以解决这个问题。
潜入源代码,我在Modules / _fileio.c中发现文件描述符被fileio_dealloc()析构函数关闭,这导致了真正的问题。
上面示例代码使用的文件对象的持续时间是多少?在该语句执行之后,该对象确实变为未引用,因此fd将在未来的垃圾收集扫描中受到真正的close(2)
调用吗?如果是这样,那么示例行是不是很好的做法,还是一个人不应该指望fd被释放,从而冒着内核每进程描述符表耗尽的风险?
答案 0 :(得分:3)
文件的持续时间是多少 示例代码返回的对象 以上?
该代码不返回文件对象(正如Q的标题所说,它接收它作为参数)。
在当前的CPython中,文件将在函数返回时关闭(因为该函数不会将对文件对象的任何引用存储到更持久的位置)。在其他实现中,文件将“最终”关闭,但没有指定精确的时间。
取决于CPython的即时关闭语义(当未来的CPython转向更好的垃圾收集机制时可能会改变),虽然这是一种非常传统的方法,但并不是最佳实践。
相反,最佳做法是使用with
语句:
with open(...) as f:
reader = pickle.load(f)
使用 this ,在所有实现中都保证文件的立即关闭(只要with
语句的主体结束)。
请注意,在Python 2.5中,您需要from __future__ import with_statement
才能使用with
。在2.6或更高版本中,为此目的不需要这样的“从未来导入”(它是无害的,但是如果你知道你将永远不会在2.5下运行它是多余的并且更好地删除了。)