在一行代码中打开读取和关闭文件

现在我用:

pageHeadSectionFile = open('pagehead.section.htm','r')
output = pageHeadSectionFile.read()
pageHeadSectionFile.close()

但是为了让代码看起来更好,我可以这样做:

output = open('pagehead.section.htm','r').read()

使用上述语法时,如何关闭文件以释放系统资源?

255185 次浏览

实际上您并不需要关闭它-Python 会在垃圾收集期间或程序退出时自动关闭它。但是正如@delnan 指出的,出于各种原因,最好明确地关闭它。

因此,你可以做些什么来保持简短、简单和明确:

with open('pagehead.section.htm', 'r') as f:
output = f.read()

现在只有两行了,我觉得还挺好读的。

使用 CPython,您的文件将在执行该行之后立即关闭,因为 file 对象将立即被垃圾收集。不过,它有两个缺点:

  1. 在不同于 CPython 的 Python 实现中,文件通常不会立即关闭,而是在以后超出您控制的时间关闭。

  2. 在 Python 3.2或更高版本中,如果启用,这将抛出 ResourceWarning

最好再加一句:

with open('pagehead.section.htm','r') as f:
output = f.read()

这将确保在所有情况下正确关闭文件。

您可以使用 with语句,并将这两个步骤写在一行中:

>>> with open('pagehead.section.htm', 'r') as fin: output = fin.read();
>>> print(output)
some content

即使在代码中发生了不好的情况,with语句也会小心地调用给定对象的 __exit__函数; 它接近于 try... finally语法。对于由 open返回的对象,__exit__对应于文件闭包。

这个语句是在 Python 2.6中引入的。

当我需要获取日志文件中已经抓取的内容周围的几行内容时,我经常这样做:

$ grep -n "xlrd" requirements.txt | awk -F ":" '{print $1}'
54


$ python -c "with open('requirements.txt') as file: print ''.join(file.readlines()[52:55])"
wsgiref==0.1.2
xlrd==0.9.2
xlwt==0.7.5

使用 伊利奥:

只有一个函数调用,而不是 file open ()、 read ()、 close ()。

from ilio import read


content = read('filename')

Python Standard Library Pathlib模块完成了您所期望的工作:

Path('pagehead.section.htm').read_text()

别忘了导入 Path:

jsk@dev1:~$ python3
Python 3.5.2 (default, Sep 10 2016, 08:21:44)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pathlib import Path
>>> (Path("/etc") / "hostname").read_text()
'dev1.example\n'

在 Python27上安装后向移植的 pathlibpathlib2

with open('pagehead.section.htm')as f:contents=f.read()

使用 more_itertools.with_iter,可以在一行(不包括导入语句)中打开、读取、关闭和分配等效的 output:

import more_itertools as mit




output = "".join(line for line in mit.with_iter(open("pagehead.section.htm", "r")))

尽管可能,我会寻找另一种方法,而不是将文件的内容分配给一个变量,即延迟迭代——这可以通过使用传统的 with块或在上面的例子中删除 join()并迭代 output来完成。

不需要为此导入任何特殊的库。

使用正常的语法,它将打开文件进行读取,然后关闭它。

with open("/etc/hostname","r") as f: print f.read()

with open("/etc/hosts","r") as f: x = f.read().splitlines()

它给出一个包含行的数组 x,可以这样打印:

for line in x: print line

这些一行程序对于维护非常有帮助——基本上是自编文档。

如果你想要那种温暖和毛茸茸的感觉,就用 吧。

对于 python 3.6,我在一个全新的 IDLE 开始下运行这两个程序,其运行时为:

0.002000093460083008  Test A
0.0020003318786621094 Test B: with guaranteed close

所以没什么区别。

#--------*---------*---------*---------*---------*---------*---------*---------*
# Desc: Test A for reading a text file line-by-line into a list
#--------*---------*---------*---------*---------*---------*---------*---------*


import sys
import time


#                                  # MAINLINE
if __name__ == '__main__':
print("OK, starting program...")


inTextFile = '/Users/Mike/Desktop/garbage.txt'


#                                  # Test: A: no 'with;
c=[]
start_time = time.time()
c = open(inTextFile).read().splitlines()
print("--- %s seconds ---" % (time.time() - start_time))


print("OK, program execution has ended.")
sys.exit()                     # END MAINLINE

产出:

OK, starting program...
--- 0.002000093460083008 seconds ---
OK, program execution has ended.


#--------*---------*---------*---------*---------*---------*---------*---------*
# Desc: Test B for reading a text file line-by-line into a list
#--------*---------*---------*---------*---------*---------*---------*---------*


import sys
import time


#                                  # MAINLINE
if __name__ == '__main__':
print("OK, starting program...")


inTextFile = '/Users/Mike/Desktop/garbage.txt'


#                                  # Test: B: using 'with'
c=[]
start_time = time.time()
with open(inTextFile) as D: c = D.read().splitlines()
print("--- %s seconds ---" % (time.time() - start_time))


print("OK, program execution has ended.")
sys.exit()                     # END MAINLINE

产出:

OK, starting program...
--- 0.0020003318786621094 seconds ---
OK, program execution has ended.

我认为实现这一点的最自然的方法是定义一个函数。

def read(filename):
f = open(filename, 'r')
output = f.read()
f.close()
return output

然后你可以做以下事情:

output = read('pagehead.section.htm')