如果我只想使用一个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'))
所以,其中任何一个都是真的,
或者这是一种不好的做法?
另外,如果我允许文件读/写,答案是否会改变?
要明确,dosomething
可能类似于np.array()
或for i in f.readlines()
答案 0 :(得分:12)
这是一种糟糕的做法。它与开放模式(读,写,读+写,附加,二进制模式,文本模式......)无关。
在CPython中,"它几乎总是有效的"因为文件对象在变为垃圾(无法访问)时会自动关闭,而CPython的引用计数通常在它变为垃圾后很快收集(非循环)垃圾。
但依靠这确实是不好的做法。
例如,如果dosomething(f)
在返回之前运行了一个小时,则文件对象在整个时间内保持打开的可能性非常大。
注意:在某些情况下,dosomething(f)
可能会被编码为显式关闭传入的文件对象本身。在那些情况下,它并非糟糕的做法; - )
后来:我经常看到的相关事情就是:
data = open(file_path).read()
在CPython中,由于CPython的引用计数,语句完成时,未命名的文件对象会立即被垃圾收集(因此也会被关闭)。当他们将代码移动到不同的Python实现时,人们会感到惊讶,并且获得OS"太多的打开文件!"投诉。嘿 - 服务对了; - )
示例:强>
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
永远不会再使用,垃圾收集,但CPython不会。)
"欢迎"可能仍在文件的内存缓冲区中,因此尚未写入磁盘。所以第三个语句可能找到一个空文件,并且什么都不打印。
在Python的其他实现中,两个示例都可以打印空行。