如何使用 open with 语句打开文件
- 2025-01-10 08:46:00
- admin 原创
- 85
问题描述:
我正在研究如何在 Python 中进行文件输入和输出。我编写了以下代码,将一个文件中的名称列表(每行一个)读入另一个文件,同时将名称与文件中的名称进行核对,并将文本附加到文件中的出现位置。代码有效。可以做得更好吗?
我想将该with open(...
语句用于输入和输出文件,但不明白它们如何位于同一个块中,这意味着我需要将名称存储在临时位置。
def filter(txt, oldfile, newfile):
'''\n 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!
'
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')
解决方案 1:
Python 允许open()
在一个 中放置多个语句with
。您可以使用逗号分隔它们。您的代码将是:
def filter(txt, oldfile, newfile):
'''\n 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!
'
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
要返回的值。)
当引入该语句时,Python 2.5 中不支持使用多个open()
项,Python 2.6 中也不支持,但 Python 2.7 和 Python 3.1 或更新版本支持该语句。with
`with`
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
。
解决方案 2:
使用像这样的嵌套块,
with open(newfile, 'w') as outfile:
with open(oldfile, 'r', encoding='utf-8') as infile:
# your logic goes right here
解决方案 3:
你可以嵌套 with 块。像这样:
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!
'
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())
解决方案 5:
从 Python 3.10 开始,我们可以使用分组括号将上下文管理器中的多个 open 语句拆分为多行。如果必须同时打开多个文件,这可以提高可读性。
例如,不要编写以下内容:
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)