【发布时间】:2018-09-05 20:50:57
【问题描述】:
考虑以下 Python (2.x) 代码:
for line in open('foo').readlines():
print line.rstrip()
我假设由于打开的文件仍然未被引用,它必须自动关闭。我已经阅读了 Python 中的垃圾收集器,它释放了未使用对象分配的内存。 GC 是否也足以处理文件?
【问题讨论】:
标签: python file garbage-collection
考虑以下 Python (2.x) 代码:
for line in open('foo').readlines():
print line.rstrip()
我假设由于打开的文件仍然未被引用,它必须自动关闭。我已经阅读了 Python 中的垃圾收集器,它释放了未使用对象分配的内存。 GC 是否也足以处理文件?
【问题讨论】:
标签: python file garbage-collection
更新
对于当前版本的 python,明确的建议是明确关闭文件或使用with 语句。没有任何迹象表明 GC 将为您关闭文件。所以现在的答案应该是:也许,但不能保证。始终使用close() 或with 语句。
Python 3.8 docs 中的文字已更新为:
如果您没有使用
with关键字,那么您应该调用 f.close() 来关闭文件并立即释放它使用的所有系统资源。警告:调用
f.write()而不使用with关键字或调用f.close()可能会导致f.write()的参数没有完全写入磁盘,即使程序成功退出。
旧答案:
如果您没有使用
with关键字,那么您应该调用f.close()来关闭文件并立即释放它使用的所有系统资源。如果您没有明确关闭文件,Python 的垃圾收集器最终会销毁该对象并为您关闭打开的文件,但该文件可能会保持打开一段时间。另一个风险是不同的 Python 实现会在不同的时间进行这种清理。
是的,文件将自动关闭,但为了控制进程,您应该自己执行此操作或使用with 声明:
with open('foo') as foo_file:
for line in foo_file.readlines():
print line.rstrip()
foo_file 将在 with 块结束后关闭
Python 2.7 docs 中的措辞不同:
当你处理完一个文件后,调用 f.close() 来关闭它并释放它 打开的文件占用的任何系统资源。打电话后 f.close(),尝试使用文件对象会自动失败。
所以我假设你不应该依赖垃圾收集器自动为你关闭文件,而只是手动/使用with
【讨论】:
with 语句。 python 3.6 中的Python’s garbage collector will eventually destroy the object and close the open file for you 不再适用
这取决于你做什么,看看这个description how it works。
一般来说我会推荐使用文件的上下文管理器:
with open("foo", "r") as f:
for line in f.readlines():
# ....
类似于(用于基本理解):
file_context_manager = open("foo", "r").__enter__()
for line in file_context_manager.readlines():
# ....
file_context_manager.__exit__()
第一个版本更具可读性,withstatement 自动调用 exit 方法(加上更多context handling)。
当with 语句的范围离开时,文件将自动关闭。
【讨论】:
__exit__(),而在 for 循环结束时没有保证清除
__enter__ 但从不调用 __exit__。
with 块扩展的确切翻译,而且要复杂得多。
我经常使用open 而不使用with,所以我进行了一些测试。对于测试,我使用 Python 3.9,所以我不是在说早期版本,但至少对于 3.9,我们不需要 with 来关闭干净的文件。
重击
inotifywait -m "testfile"
python3.9
lines=[line for line in open("testfile")]
sleep(5)
for line in lines:
print(line)
观看inotifywait 窗口并运行python 脚本。在睡眠之前,最终事件将是CLOSE_NOWRITE,CLOSE,并且通过运行 python 脚本不会有来自该文件的其他事件。
【讨论】: