8

如果我只想使用一次file对象,通常我仍然会使用with块或file在完成后显式关闭对象,因为关闭文件似乎是正确的做法:

with open('filename','r') as f:
    x = dosomething(f)

或者

f = open('filename','r')
x = dosomething(f)
f.close()

但是,我看到人们使用将调用open直接传递给函数而不将输出保存到任何变量,从而无法显式关闭:

x = dosomething(open('filename','r'))

那么,这些都是真的吗,

  1. 不知何故,未命名的文件对象被关闭
  2. 没关系,不关闭文件就好了

或者这是一个不好的做法?

另外,如果我允许文件被读/写,答案会改变吗?

需要明确的是,dosomething可能类似于np.array()for i in f.readlines()

4

1 回答 1

12

这是一个糟糕的做法。它与打开模式(读、写、读+写、追加、二进制模式、文本模式...)无关。

在 CPython 中,“它几乎总是有效”,因为文件对象在变成垃圾(无法访问)时会自动关闭,而 CPython 的引用计数通常会在垃圾变成垃圾后很快收集(非循环)垃圾。

但依靠它确实是不好的做法。

例如,如果dosomething(f)在返回之前运行了一个小时,文件对象很有可能会一直保持打开状态。

注意:在某些情况下,dosomething(f)可能会被编码为显式关闭传入的文件对象本身。在这些情况下,这不是糟糕的做法;-)

后来:我经常看到的相关事情是这样的:

data = open(file_path).read()

在 CPython 中,由于 CPython 的引用计数,当语句完成时,未命名的文件对象会立即被垃圾收集(因此也被关闭)。当人们将他们的代码移动到不同的 Python 实现时,他们会感到惊讶,并让操作系统“打开的文件太多!” 投诉。嘿-为他们服务;-)

例子:

open("Output.txt", "w").write("Welcome")
print open("Output.txt").read()

这打印

Welcome

在 CPython 中,因为第一条语句中的未命名文件对象在第一条语句结束时立即被垃圾收集(并关闭)。

但:

output = open("Output.txt", "w")
output.write("Welcome")
print open("Output.txt").read()

可能在 CPython 中打印一个空行。在这种情况output,文件对象绑定到一个名称(.output

“欢迎”可能仍在文件的内存缓冲区中,因此尚未写入磁盘。所以第三条语句可能会找到一个空文件,并且什么也不打印。

在 Python 的其他实现中,这两个示例都可以打印空行。

于 2013-10-15T03:01:06.690 回答