显式关闭文件重要吗?

在 Python 中,如果您打开一个文件而不调用 close(),或者关闭该文件但不使用 try-finally或“ with”语句,这是一个问题吗?或者,作为一种编码实践,依赖 Python 垃圾收集来关闭所有文件是否足够?例如,如果有人这样做:

for line in open("filename"):
# ... do stuff ...

... 这是一个问题,因为该文件永远不能被关闭,并可能发生异常,阻止它被关闭?或者它肯定会在 for语句结束时关闭,因为文件超出了作用域?

86684 次浏览

该文件确实被垃圾收集,因此被关闭。GC 决定何时关闭,而不是您。显然,这不是一种推荐的做法,因为如果您不在使用完文件后立即关闭它们,您可能会达到打开文件句柄的限制。如果在你的 for循环中,你打开了更多的文件并且让它们停留在那里,会怎么样呢?

有些 Python 会在不再被引用时自动关闭文件,而其他的则不会,当 Python 解释器退出时,由 O/S 来关闭文件。

即使对于将为您关闭文件的 Python,时间也不能保证: 可能是立即关闭,也可能是几秒/几分钟/几小时/几天后关闭。

因此,虽然您使用的 Python 可能不会遇到问题,但是保持文件打开肯定不是一个好的做法。事实上,在 cpython3中,您现在会收到警告,如果您没有这样做,系统必须为您关闭文件。

寓意: 自己收拾干净。 :)

在您的示例中,不能保证在解释器退出之前关闭该文件。在当前版本的 CPython 中,该文件将在 for 循环的末尾关闭,因为 CPython 使用引用计数作为其主要的垃圾收集机制,但这是实现细节,而不是该语言的一个特性。其他 Python 实现并不能保证以这种方式工作。例如 IronPython、 PyPy 和 Jython 不使用引用计数,因此不会在循环结束时关闭文件。

依赖 CPython 的垃圾收集实现是不好的做法,因为它会降低代码的可移植性。如果使用 CPython,可能不会出现资源泄漏,但如果切换到不使用引用计数的 Python 实现,则需要检查所有代码并确保所有文件都正确关闭。

举个例子:

with open("filename") as f:
for line in f:
# ... do stuff ...

尽管在这种特殊情况下使用这种结构是相当安全的,但对于推广这种做法有一些警告:

  • Run 可能会用完文件描述符,尽管不太可能,想象一下如何捕获这样的 bug
  • 你可能无法在某些系统上删除该档案,例如 win32
  • 如果您运行除 CPython 之外的任何程序,则不知道文件何时关闭
  • 如果以写或读写模式打开文件,则不知道什么时候刷新数据

嗨,当您要在同一个 python 脚本中使用文件描述符的内容时,关闭文件描述符是非常重要的。经过这么长时间的调试,我今天才意识到。原因是内容将被编辑/删除/保存只有在您关闭您的文件描述符和更改文件受到影响!

因此,假设您有这样一种情况: 将内容写入一个新文件,然后在不关闭 fd 的情况下,在另一个读取其内容的 shell 命令中使用该文件(而不是 fd)。在这种情况下,您将无法得到预期的 shell 命令的内容,如果您尝试调试,则无法轻松找到 bug。你也可以在我的博客条目 http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html中阅读更多

在 I/O 过程中,数据被缓冲: 这意味着在写入文件之前,数据被保存在一个临时位置。

Python 不会刷新缓冲区ーー也就是说,将数据写入文件ーー直到确定您已经完成了写入操作。一种方法是关闭文件。

如果不关闭文件就写入文件,则数据将无法到达目标文件。

Python 使用 close ()方法关闭打开的文件。一旦文件关闭,您就不能再次读/写该文件中的数据。

如果您尝试再次访问同一个文件,它将引发 价值错误,因为该文件已经关闭。

如果引用对象已被分配给另一个文件,Python 将自动关闭该文件。关闭文件是一种标准做法,因为它降低了被无保证地修改的风险。

解决这个问题的另一种方法是...

如果使用 with 语句打开文件,将保留一个临时变量用于访问该文件,并且只能使用缩进块访问该文件。语句本身在执行缩进代码后调用 close ()方法。

句法:

with open('file_name.text') as file:


#some code here