【问题标题】:opened file descriptors in python在python中打开的文件描述符
【发布时间】:2012-11-09 20:30:11
【问题描述】:

当我在 IPython3 shell 中使用这段代码时

 >>>data = open('file').read()

然后检查打开的文件描述符:

 lsof | grep file

我找到空列表

当我使用这个时:

>>>open('file')

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

当我重新分配值时,我知道解释器中的 '_' var

>>>111
>>>_
111

但描述符保持打开状态。 当我重复

>>>open('file')

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

【问题讨论】:

  • 您使用的是哪个 Python shell?在默认的 Python shell 中,在 Python 2.7.3 中,一旦输入第二个表达式,即重新分配 _ 的表达式,文件描述符就会被释放。
  • 没问题;但是,我也不能用 Python 3.3.0 重复它。我执行open('somefile'),在另一个shell 中lsof 显示要打开的文件。然后我执行1+1,在shell中lsof显示文件未打开。

标签: python file python-3.x


【解决方案1】:

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

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

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

【讨论】:

  • 如果我重复 open('file') n 次将会有 2 * n 个打开的描述符
  • @adray 你是怎么得出这个结论的?对open 的一次调用应对应于一个打开的文件描述符。
  • @adray 我不能用 Python 2.7.3 重复这一点;在问题下查看我的评论。
  • @adray 你能给我们看一个例子吗?我也没看到。
【解决方案2】:

这是因为您使用的交互式解释器保留了对返回的最后一个对象的隐式引用。该引用被命名为_

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

该文件现在已关闭,因为它不再被引用。

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

【讨论】:

    【解决方案3】:

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

    第二个版本相当于这样:

    _ = open('file')
    

    由于_ 仍然引用该文件,因此在您运行另一个命令之前它仍然有效。

    请注意,此行为特定于 CPython。 IronPython 等其他实现可能不会那么快地关闭文件,因此您应该在使用完文件后真正关闭它们。一个很好的方法是使用with statement

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

    相关

    【讨论】:

    • 要补充一点,这里要指出的是,在第一种情况下,文件描述符对象没有返回,文件的内容是。由于 python 的解释器允许您通过&gt;&gt;&gt; _ 获取最后一个命令的结果,因此第二个实例仍然具有对可用文件描述符的引用。
    猜你喜欢
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多