明确关闭文件重要吗?
- 2024-12-04 08:56:00
- admin 原创
- 159
问题描述:
在 Python 中,如果你打开文件而不调用close()
,或者关闭文件但不使用try
-finally
或“ with
”语句,这会是个问题吗?或者,作为一种编码实践,依赖 Python 垃圾收集来关闭所有文件就足够了吗?例如,如果这样做:
for line in open("filename"):
# ... do stuff ...
for
... 这是一个问题吗?因为文件永远无法关闭,并且可能会发生异常导致文件无法关闭?还是由于文件超出范围,它肯定会在语句结束时关闭?
解决方案 1:
在您的示例中,文件不能保证在解释器退出之前关闭。在当前版本的 CPython 中,文件将在 for 循环结束时关闭,因为 CPython 使用引用计数作为其主要垃圾收集机制,但这是实现细节,而不是语言的功能。Python 的其他实现不能保证以这种方式工作。例如,IronPython、PyPy 和 Jython 不使用引用计数,因此不会在循环结束时关闭文件。
依赖 CPython 的垃圾收集实现是一种不好的做法,因为它会降低代码的可移植性。如果使用 CPython,可能不会出现资源泄漏,但如果您切换到不使用引用计数的 Python 实现,则需要检查所有代码并确保所有文件都已正确关闭。
供您示例使用:
with open("filename") as f:
for line in f:
# ... do stuff ...
解决方案 2:
有些 Python 会在不再引用文件时自动关闭文件,而有些 Python 则不会,而是由操作系统在 Python 解释器退出时决定是否关闭文件。
即使 Python 会为您关闭文件,也不能保证时间:可能是立即关闭,也可能是几秒/几分钟/几小时/几天后关闭。
因此,虽然您可能不会遇到使用 Python 时出现的问题,但让文件保持打开状态绝对不是一个好习惯。事实上,在 cpython 3 中,如果您不关闭文件,您将收到系统必须为您关闭文件的警告。
寓意:自己清理干净。:)
解决方案 3:
虽然在这种特殊情况下使用这种构造是相当安全的,但推广这种做法仍有一些注意事项:
运行可能会耗尽文件描述符,尽管可能性不大,但想象一下寻找这样的错误
在某些系统上,您可能无法删除该文件,例如 win32
如果你运行 CPython 以外的任何程序,你不知道文件何时关闭
如果以写入或读写模式打开文件,则不知道数据何时被刷新
解决方案 4:
该文件确实会被垃圾收集器收集,因此会被关闭。GC 决定何时关闭它,而不是您。显然,这不是推荐的做法,因为如果您在使用完文件后不立即关闭文件,您可能会达到打开文件句柄的限制。如果在for
您的循环中,您打开了更多文件并让它们停留在原处,该怎么办?
解决方案 5:
你好,当你打算在同一个 Python 脚本中使用文件描述符的内容时,关闭文件描述符非常重要。经过这么长时间的调试,我今天才意识到这一点。原因是只有在关闭文件描述符后,内容才会被编辑/删除/保存,并且更改才会影响文件!
假设您遇到这种情况:您将内容写入新文件,然后不关闭 fd 而在另一个读取其内容的 shell 命令中使用该文件(不是 fd)。在这种情况下,您将无法按预期获得 shell 命令的内容,如果您尝试调试,则无法轻松找到错误。您还可以在我的博客文章http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html中阅读更多内容
解决方案 6:
在 I/O 过程中,数据会被缓冲:这意味着数据在写入文件之前会被保存在一个临时位置。
Python 不会刷新缓冲区(即,将数据写入文件),直到它确定您已完成写入。执行此操作的一种方法是关闭文件。
如果您写入文件而不关闭,数据将不会写入目标文件。
解决方案 7:
Python 使用 close() 方法关闭打开的文件。一旦文件关闭,您就无法再次读取/写入该文件中的数据。
如果您尝试再次访问同一个文件,它会引发ValueError,因为该文件已经关闭。
如果引用对象已分配给其他文件,Python 会自动关闭该文件。关闭文件是一种标准做法,因为它可以降低被无端修改的风险。
解决这个问题的另一种方法是...使用语句
如果使用 with 语句打开文件,则会保留一个临时变量用于访问文件,并且只能使用缩进的块来访问它。With 语句本身在执行缩进的代码后调用 close() 方法。
句法:
with open('file_name.text') as file:
#some code here