Python中如何计算文件对象在参数列表中的持续时间
在pickle模块的文档中,有一段示例代码:
reader = pickle.load(open('save.p', 'rb'))
我第一次看到这段代码时,觉得它会分配一个系统文件描述符,读取它的内容,然后“泄漏”这个打开的描述符,因为没有任何方法可以调用close()
来关闭它。这让我开始想,是否有一些隐藏的机制来处理这种情况。
深入查看源代码,我在Modules/_fileio.c中发现,文件描述符是通过fileio_dealloc()这个析构函数来关闭的,这让我产生了一个更深层次的问题。
那么,上面示例代码中使用的文件对象的生命周期是多久呢?在那条语句执行后,这个对象是否真的变得没有引用了?因此,文件描述符是否会在将来的垃圾回收时被真正调用close(2)
来关闭?如果是这样的话,这行示例代码算不算好习惯,还是说不应该指望文件描述符会被释放,从而导致内核的每个进程的描述符表耗尽的风险呢?
1 个回答
上面示例代码返回的文件对象的持续时间是多少?
那段代码并没有返回文件对象(正如问题标题所说,它是作为参数传入的)。
在当前的CPython中,文件会在函数返回时关闭(因为函数没有把文件对象的引用保存到更持久的地方)。在其他实现中,文件会“最终”关闭,但没有具体的时间说明。
根据CPython的立即关闭语义(这可能会在未来的CPython版本中改进垃圾回收机制时发生变化),虽然这种传统方法是常见的,但并不是最佳实践。
更好的做法是使用with
语句:
with open(...) as f:
reader = pickle.load(f)
使用这个方法,文件会在with
语句的主体结束时立即关闭,这在所有实现中都是有保证的。
需要注意的是,在Python 2.5中,你需要使用from __future__ import with_statement
来使用with
。在2.6或更高版本中,这种“从未来导入”的做法就不再需要了(虽然这样做没有坏处,但如果你确定不会在2.5版本下运行,去掉它会更好)。