Python 是否需要关闭没有引用的文件?

Python 是否需要关闭没有引用的文件?,python,python-2.7,file,Python,Python 2.7,File,作为一个完全的编程初学者,我试图理解打开和关闭文件的基本概念。我正在做的一个练习是创建一个脚本,允许我将内容从一个文件复制到另一个文件 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).

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

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_文件和out_文件变量。但是,这是否会让我有两个打开的文件,但没有任何引用它们的内容?我该如何关闭这些,还是不需要关闭


我们非常感谢您对本主题的任何帮助。

处理此问题的python方法是使用:


与此类文件一起使用时,
with
将确保为您完成所有必要的清理,即使
read()
write()
抛出错误。

打开文件而不必担心未关闭文件的安全方法如下:

with open(from_file, 'r') as in_file:
    in_data = in_file.read()

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

在处理文件对象时,最好使用
关键字。这样做的好处是,即使在执行过程中引发异常,文件也会在其套件完成后正确关闭。它也比编写等效的try-finally块短得多:

>>> with open('workfile', 'r') as f:
...     read_data = f.read()
>>> f.closed
True

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

就你而言,做什么

open(to_file, 'w').write(indata)
将为
创建一个文件对象,但不将其指定为名称-这意味着没有对其的引用。您不可能在这一行之后操纵对象

CPython将检测到这一点,并在使用后清理对象。对于文件,这意味着自动关闭它。原则上,这很好,并且您的程序不会泄漏内存

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

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

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


TLDR:它可以工作,但请不要这样做。

在使用python时,到目前为止的答案是绝对正确的。您应该将
与open()一起使用
上下文管理器。这是一个很棒的内置功能,有助于简化常见的编程任务(打开和关闭文件)

但是,由于您是初学者,无法访问 在你的整个职业生涯中,我将从一般编程的角度来解决这个问题

代码的第一个版本非常好。打开一个文件,保存引用,从文件中读取,然后关闭它。这就是当语言没有为任务提供快捷方式时编写大量代码的方式。我唯一需要改进的是将
close()
移动到打开和读取文件的位置。打开并读取文件后,内存中就有了内容,不再需要打开该文件

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

out_file = open(to_file, 'w')
out_file.write(indata)
in_file.close()
您询问了“基本概念”,因此让我们从头开始:当您打开一个文件时,您的程序将获得对系统资源的访问权,,也就是说,访问程序自身内存空间之外的内容。这基本上是操作系统提供的一点魔力(Unix术语中的系统调用)。文件对象中隐藏的是对“文件描述符”的引用,即与打开的文件关联的实际操作系统资源。关闭文件会告诉系统释放此资源

作为一种操作系统资源,一个进程可以保持打开的文件数量是有限的:很久以前,Unix上每个进程的限制大约是20个。现在,我的OSX设备限制了256个打开的文件(尽管这是一个强加的限制,可以提高)。其他系统可能会在中设置限制(每个用户,而不是本例中的每个进程)。当程序结束时,所有资源将自动释放。因此,如果你的程序打开了几个文件,对它们做了一些处理,然后退出,你可能会变得马虎,你永远不会知道其中的区别。但是,如果您的程序将打开数千个文件,那么最好释放打开的文件以避免超过操作系统的限制

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

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

  • 显式地使用
    close()
    。(python新手注意:别忘了parens!我的学生喜欢在_文件中编写
    。close
    ,它什么都不做。)

  • 建议:通过使用
    with
    语句打开文件来隐式执行。
    close()
    方法将在到达
    with
    块的末尾时调用,即使是在异常终止的情况下(来自异常)

  • 如果您的python引擎实现了引用管理器或垃圾收集器,则它将隐式地由引用管理器或垃圾收集器执行。这是不推荐的,因为它不是完全便携的;见第
    in_file = open(from_file)
    indata = in_file.read()
    out_file.close() 
    
    out_file = open(to_file, 'w')
    out_file.write(indata)
    in_file.close()
    
    with open("data.txt") as in_file:
        data = in_file.read()