要添加到James Mills' answer,如果需要了解没有看到任何错误的具体原因:
Python定义当一个文件被垃圾回收时,它将自动关闭。但是Python将如何处理垃圾收集留给了实现。您可能正在使用的CPython实现使用引用计数:一旦对对象的最后一个引用消失,它就会立即被收集。因此,所有这些都将在CPython中起作用:def spam():
for i in range(100000):
open('spam.txt') # collected at end of statement
def eggs():
for i in range(100000):
f = open('eggs.txt') # collected next loop, when f is reassigned
def beans():
def toast():
f = open('toast.txt') # collected when toast exits
for i in range(100000):
toast()
但是许多其他实现(包括其他三大实现pypyy、Jython和IronPython)使用更智能的垃圾收集器,可以动态地检测垃圾,而不必跟踪所有引用。这使得它们更高效,更擅长线程处理等,但这意味着当一个对象被收集时,它是不确定的。所以同样的代码行不通。或者,更糟的是,它将在你的60个测试中起作用,然后在你为你的投资者做演示时就失败了。在
如果您需要PyPy的速度或IronPython的.NET集成,但如果不重写所有代码就不能拥有它,那就太可惜了。或者,如果其他人想使用您的代码,但需要它在Jython中工作,而不得不另寻他处。在
同时,即使在CPython中,解释器也不会在关闭时收集所有垃圾。(它越来越好,但即使在3.4版本中也不完美)所以在某些情况下,你需要依靠操作系统来关闭你的文件。操作系统通常会在刷新时刷新它们,但如果你在守护进程线程中打开了它们,或者你用os._exit退出,或者出现错误,则可能不会。(当然,如果你被电源线绊倒而退出,当然也不会。)
最后,即使是CPython(我想是从3.3开始)也有专门的代码来生成警告,如果你让你的文件被垃圾回收而不是关闭它们。这些警告在默认情况下是关闭的,但是人们经常建议打开它们,总有一天它可能会发生。在