是否需要关闭不参考它们的文件?

作为一个完整的编程初学者,我想了解打开和关闭文件的基本概念。 我正在做的一个练习是创建一个脚本,允许我将内容从一个文件复制到另一个文件。

in_file = open(from_file)
indata = in_file.read()

out_file = open(to_file, 'w')
out_file.write(indata)

out_file.close()
in_file.close()

我试图缩短这段代码,并提出了这个问题:

indata = open(from_file).read()
open(to_file, 'w').write(indata)

这对我来说看起来效率更高。 但是,这也是我感到困惑的地方。 我想我忽略了对打开文件的引用; 没有必要使用in_file和out_file变量。 但是,这是否会给我提供两个打开的文件,但没有提及它们? 我如何关闭这些设备,或者没有必要?

非常感谢任何有助于阐明这个主题的帮助。


您询问了有关“基本概念”的内容,让我们从顶层开始:当您打开一个文件时,您的程序可以访问系统资源,即访问程序自身内存空间之外的某个资源 。 这基本上是由操作系统提供的一点魔力(一个系统调用,在Unix术语中)。 隐藏在文件对象中的是对“文件描述符”的引用,该文件描述符是与打开文件关联的实际操作系统资源。 关闭文件告诉系统释放该资源。

作为一种操作系统资源, 一个进程可以保持打开的文件数量是有限的:很久以前,Unix上每进程的限制大约是20。 现在我的OS X盒子限制了256个打开的文件(尽管这是一个限制,并且可以提高)。 其他系统可能会限制几千个或几万个(每个用户,而不是这个例子中的每个进程)。 当程序结束时,所有资源都会自动释放。 所以如果你的程序打开几个文件,对它们做某些事情并退出,你可能会马虎,你永远不会知道它们的差异。 但是,如果您的程序将打开数千个文件,那么您最好释放打开的文件以避免超出操作系统限制。

在流程退出之前关闭文件还有另外一个好处:如果您打开一个文件进行写入, 关闭文件将首先“刷新其输出缓冲区”。 这意味着I / O库通过收集(“缓冲”)您写出的内容并批量保存到磁盘来优化磁盘使用。 如果您将文本写入文件并立即尝试重新打开并在不首先关闭输出句柄的情况下读取它,则会发现并非所有内容都已写出。 另外,如果你的程序太紧急(有信号,偶尔甚至通过正常退出),输出可能永远不会被刷新。

关于如何发布文件已经有很多其他的答案,所以这里只是一个简要的方法列表:

  • 显式使用close() 。 (python新手注意:不要忘记in_file.close !我的学生喜欢写in_file.close ,它什么都不做。)

  • 建议:隐含地说,用with语句打开文件。 即使在异常终止(来自异常)的情况下,也会在达到with块的末尾时调用close()方法。

    with open("data.txt") as in_file:
        data = in_file.read()
    
  • 由引用管理器或垃圾收集器隐含,如果你的python引擎实现它。 这是不推荐的,因为它不是完全可移植的; 详情请参阅其他答案。 这就是为什么with语句被添加到python的原因。

  • 隐含地,当你的程序结束时。 如果文件打开输出,这可能会导致程序在所有内容刷新到磁盘之前退出。


  • 处理这个问题的pythonic方法是使用with context manager:

    with open(from_file) as in_file, open(to_file, 'w') as out_file:
        indata = in_file.read()
        out_file.write(indata)
    

    与这样的文件with将确保为您完成所有必要的清理,即使read()write()抛出错误。


    默认的python interpeter CPython使用引用计数。 这意味着一旦没有对象的引用,它就会被垃圾收集,即清理。

    在你的情况下,这样做

    open(to_file, 'w').write(indata)
    

    将为to_file创建一个文件对象,但不会将它命名为名称 - 这意味着没有对它的引用。 这条线以后你不可能操纵对象。

    CPython会检测到它,并在使用后清理该对象。 在文件的情况下,这意味着自动关闭它。 原则上,这很好,你的程序不会泄漏内存。

    “问题”是这种机制是CPython解释器的实现细节。 语言标准明确无法保证! 如果您使用的是替代解释器,如pypy,则文件的自动关闭可能会无限期地延迟。 这包括其他隐式操作,例如在关闭时刷新写入。

    这个问题也适用于其他资源,例如网络套接字。 始终明确处理这些外部资源是一种良好的做法。 自Python 2.6以来, with语句使得这个优雅:

    with open(to_file, 'w') as out_file:
        out_file.write(in_data)
    

    TLDR:它有效,但请不要这样做。

    链接地址: http://www.djcxy.com/p/53147.html

    上一篇: Is there a need to close files that have no reference to them?

    下一篇: Creating a new dict in Python