显式关闭文件重要吗?

2022-01-16 00:00:00 python file garbage-collection

问题描述

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

In Python, if you either open a file without calling close(), or close the file but not using try-finally or the "with" statement, is this a problem? Or does it suffice as a coding practice to rely on the Python garbage-collection to close all files? For example, if one does this:

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

...这是一个问题,因为文件永远无法关闭,并且可能发生阻止它被关闭的异常?还是肯定会因为文件超出范围而在 for 语句结束时关闭?

... is this a problem because the file can never be closed and an exception could occur that prevents it from being closed? Or will it definitely be closed at the conclusion of the for statement because the file goes out of scope?


解决方案

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

In your example the file isn't guaranteed to be closed before the interpreter exits. In current versions of CPython the file will be closed at the end of the for loop because CPython uses reference counting as its primary garbage collection mechanism but that's an implementation detail, not a feature of the language. Other implementations of Python aren't guaranteed to work this way. For example IronPython, PyPy, and Jython don't use reference counting and therefore won't close the file at the end of the loop.

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

It's bad practice to rely on CPython's garbage collection implementation because it makes your code less portable. You might not have resource leaks if you use CPython, but if you ever switch to a Python implementation which doesn't use reference counting you'll need to go through all your code and make sure all your files are closed properly.

您的示例使用:

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

相关文章