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

问题描述 投票:0回答:5

我正在研究如何在 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')
python file python-3.x file-io io
5个回答
391
投票

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.5 或 Python 2.6 中不支持将多个
with
项与
with
一起使用,但在 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


41
投票

像这样使用嵌套块,

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

14
投票

你可以用块嵌套你的。像这样:

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 语句中拥有多个上下文管理器,如 @steveha 所描述的那样。在我看来,这似乎是比嵌套更好的选择。

对于你的最后一个小问题,退货没有真正的目的。我会把它删除。


4
投票
有时,您可能想要打开不同数量的文件并对每个文件进行相同的处理,您可以使用

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())
    

0
投票

自Python 3.10起,我们可以使用分组括号将上下文管理器中的多个打开语句分成多行。如果必须同时打开多个文件,这可以提高可读性。

例如,不要写以下内容:

with open(newfile, 'w') as outfile, open(oldfile1, 'r', encoding='utf-8') as infile1, open(oldfile2, 'r', encoding='utf-8') as infile2: for line1, line2 in zip(infile1, infile2): if line1 in line2: outfile.write(line1)
我们可以写以下内容:

with ( open(newfile, 'w') as outfile, open(oldfile1, 'r', encoding='utf-8') as infile1, open(oldfile2, 'r', encoding='utf-8') as infile2, ): for line1, line2 in zip(infile1, infile2): if line1 in line2: outfile.write(line1)
    
© www.soinside.com 2019 - 2024. All rights reserved.