如何使用open with语句打开文件

时间:2012-02-14 19:26:53

标签: python file python-3.x file-io io

我正在研究如何在Python中进行文件输入和输出。我编写了以下代码来读取文件中的名称列表(每行一个)到另一个文件,同时根据文件中的名称检查名称,并将文本附加到文件中的出现位置。代码有效。可以做得更好吗?

我想对输入和输出文件使用with open(...语句,但无法看到它们在同一块中的含义,这意味着我需要将名称存储在临时位置。

def filter(txt, oldfile, newfile):
    '''\
    Read a list of names from a file line by line into an output file.
    If a line begins with a particular name, insert a string of text
    after the name before appending the line to the output file.
    '''

    outfile = open(newfile, 'w')
    with open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

    outfile.close()
    return # Do I gain anything by including this?

# input the name you want to check against
text = input('Please enter the name of a great person: ')    
letsgo = filter(text,'Spanish', 'Spanish2')

4 个答案:

答案 0 :(得分:271)

Python允许将多个open()语句放在一个with中。你可以用逗号分隔它们。那么你的代码就是:

def filter(txt, oldfile, newfile):
    '''\
    Read a list of names from a file line by line into an output file.
    If a line begins with a particular name, insert a string of text
    after the name before appending the line to the output file.
    '''

    with open(newfile, 'w') as outfile, open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

# input the name you want to check against
text = input('Please enter the name of a great person: ')    
letsgo = filter(text,'Spanish', 'Spanish2')

不,你在函数结尾处放置一个明确的return就没有获得任何东西。您可以使用return提前退出,但最后会使用它,并且该功能将在没有它的情况下退出。 (当然,对于返回值的函数,可以使用return指定要返回的值。)

在引入open()语句时,或在Python 2.6中,Python 2.5中不支持使用多个withwith,但Python 2.7和Python 3.1支持它或新。

http://docs.python.org/reference/compound_stmts.html#the-with-statement http://docs.python.org/release/3.1/reference/compound_stmts.html#the-with-statement

如果您编写的代码必须在Python 2.5,2.6或3.0中运行,请将with语句嵌套为建议的其他答案,或使用contextlib.nested

答案 1 :(得分:24)

使用这样的嵌套块,

with open(newfile, 'w') as outfile:
    with open(oldfile, 'r', encoding='utf-8') as infile:
        # your logic goes right here

答案 2 :(得分:10)

您可以使用块嵌套。像这样:

with open(newfile, 'w') as outfile:
    with open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

这比您的版本更好,因为您保证即使您的代码遇到异常,outfile也将关闭。显然你可以用try / finally做到这一点,但是with是正确的方法。

或者,正如我刚刚了解到的,您可以在with语句中将多个上下文管理器作为described by @steveha。在我看来,这比嵌套更好。

对于你的最后一个小问题,回报没有任何实际意义。我会删除它。

答案 3 :(得分:1)

有时候,您可能想打开可变数量的文件,并对待每个文件相同,可以使用contextlib

from contextlib import ExitStack
filenames = [file1.txt, file2.txt, file3.txt]

with open('outfile.txt', 'a') as outfile:
    with ExitStack() as stack:
        file_pointers = [stack.enter_context(open(file, 'r')) for file in filenames]                
            for fp in file_pointers:
                outfile.write(fp.read())