关于python:在1行代码中打开读取和关闭文件

open read and close a file in 1 line of code

现在我使用:

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

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

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

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


您不必关闭它 - Python将在垃圾收集期间或程序退出时自动执行此操作。但正如@delnan指出的那样,出于各种原因明确关闭它是更好的做法。

那么,你可以做些什么来保持简短,明确:

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

我认为现在它只有两行而且非常易读。


Python标准库Pathlib模块可以满足您的需求:

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

别忘了导入路径:

1
2
3
4
5
6
7
8
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
'

在Python 27上安装backported pathlibpathlib2


使用CPython,您的文件将在执行该行后立即关闭,因为文件对象会立即被垃圾回收。但有两个缺点:

  • 在与CPython不同的Python实现中,文件通常不会立即关闭,而是在以后的时间内,超出您的控制范围。

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

  • 最好再投资一条线:

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

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


    无需导入任何特殊库来执行此操作。

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

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

    要么

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

    它给你一个包含线条的数组x,可以这样打印:

    1
    for line in x: print line

    这些单行程对维护非常有帮助 - 基本上是自我记录。


    你可以做的是使用with语句:

    1
    2
    >>> with open('pagehead.section.htm', 'r') as fin:
    ...     output = fin.read()

    即使代码中发生了错误,with语句也会小心调用给定对象的__exit__函数;它接近try... finally语法。对于open返回的对象,__exit__对应于文件关闭。

    Python 2.6引入了这个语句。


    使用ilio :(内联io):

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

    1
    2
    3
    from ilio import read

    content = read('filename')


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


    如果你想要那种温暖而模糊的感觉。

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

    1
    2
    0.002000093460083008  Test A
    0.0020003318786621094 Test B: with guaranteed close

    所以差别不大。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #--------*---------*---------*---------*---------*---------*---------*---------*
    # 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

    OUTPUT:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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

    OUTPUT:

    1
    2
    3
    OK, starting program...
    --- 0.0020003318786621094 seconds ---
    OK, program execution has ended.

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

    1
    2
    3
    4
    import more_itertools as mit


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

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


    我经常做这样的事情,当我需要在日志文件中找到一些我想要的东西时:

    1
    2
    3
    4
    5
    6
    7
    $ 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