关于在Python中关闭文件

2024-06-16 12:38:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道在Python中不再使用close关闭文件是一个好习惯。我试图打开大量打开的文件,而不是关闭它们(在同一个Python进程中),但是没有看到任何异常或错误。我试过Mac和Linux。所以,想知道Python是否足够聪明,可以管理文件句柄来自动关闭/重用它们,这样我们就不需要关心文件关闭了吗?在

提前谢谢你, 林


Tags: 文件close进程linuxmac错误句柄习惯
3条回答

您确实需要在Python中关闭(输出)文件。在

其中一个例子就是将输出刷新到它们。如果您没有正确关闭文件,并且您的程序由于某种原因被终止,则左侧打开的文件可能已损坏。在

另外,还有一个:Why python has limit for count of file handles?

Python通常会垃圾收集对象不再使用,也不再被引用。这意味着完全有可能清理并关闭与垃圾收集器过滤器匹配的打开文件对象。但是;您不应依赖于此,而应使用:

with open(..):

示例也是最佳实践):

^{pr2}$

NB:如果您不关闭文件并将“打开的文件描述符”保留在系统上,那么您最终将开始触及系统的资源限制,特别是“ulimit”。你最终会看到与“打开的文件太多”相关的操作系统错误。(这里假设是Linux,但其他操作系统也会有类似的行为。在

重要提示:关闭您编写的所有打开的文件也是一个很好的做法,这样您编写的数据就会被正确刷新。这有助于确保数据的完整性,并且不会因为应用程序崩溃而使文件意外地包含损坏的数据。在

It's worth noting that the above important note is the cause of many issues with where you write to a file; read it back; discover it's empty; but then close your python program; read it in a text editor and realize it's not empty.

演示:如果不确保关闭打开的文件,可能会遇到的资源限制和错误的一个很好的示例:

$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> xs = [open("/dev/null", "r") for _ in xrange(100000)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 24] Too many open files: '/dev/null'

要添加到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开始)也有专门的代码来生成警告,如果你让你的文件被垃圾回收而不是关闭它们。这些警告在默认情况下是关闭的,但是人们经常建议打开它们,总有一天它可能会发生。在

相关问题 更多 >