这是我试图完成的这段代码:
elif parameter == 'statistics':
outfile.write(stats(infile))
for line in infile:
outfile.write(line)
因此,从本质上讲,我正在尝试将文件的统计信息写入正在复制的新文件中。统计数据有效,当我打开文件时,统计数据都被写入。但是,我注意到由于两个outfile.write,它似乎在第一个之后关闭,因此只有统计信息进入,而不是原始文件中的其余内容。
我得到的错误是这样的:
ValueError: I/O operation on closed file.
我不确定为什么文件正在关闭。
编辑:这是整个代码,根据要求
def copy_file():
infile_name = input("Please enter the name of the file to copy: ")
infile = open(infile_name, 'r', encoding='utf8')
parameter = input("Please enter a parameter(line numbers, Gutenberg trim, statistics, none): ")
outfile_name = input("Please enter the name of the new copy: ")
outfile = open(outfile_name, 'w', encoding='utf8')
counter = 1
if parameter == 'line numbers':
for line in infile:
outfile.write(f' {counter:6}: {line}')
counter += 1
elif parameter == 'Gutenberg trim':
copyStart = False
for line in infile:
#print(line.strip())
if '*** START' in line.strip():
copyStart = True
continue
elif '*** END' in line.strip():
copyStart = False
break
if copyStart == True:
outfile.write(line)
elif parameter == 'statistics':
outfile.write(stats(infile))
for line in infile:
outfile.write(line)
else:
for line in infile:
outfile.write(line)
infile.close()
outfile.close()
copy_file()
编辑2:很抱歉没有包括它。这是统计函数:
def stats(text) -> str:
with text as infile:
totallines = 0
emplines = 0
characters = 0
for line in infile:
totallines += 1
characters += len(line)
if len(line.strip()) == 0:
emplines += 1
lines = totallines - emplines
totalaveChars = characters/totallines
nonempaveChars = characters/lines
result = (f'{totallines:5} lines in list n'
f'{emplines:5} empty lines in list n'
f'{totalaveChars:5.1f} average characters per line n'
f'{nonempaveChars:5.1f} average chars per non-empty line')
return result
print(stats(open('ASH.txt', 'r', encoding='utf8')))
以下是统计数据的结果:
13052 lines in list
2666 empty lines in list
44.6 average characters per line
56.0 average chars per non-empty line
问题出在stats
函数上。with 语句将使用本地名称文本关闭文件,在您的情况下是 infile!
def stats(text) -> str:
totallines = 0
emplines = 0
characters = 0
for line in text:
totallines += 1
characters += len(line)
if len(line.strip()) == 0:
emplines += 1
lines = totallines - emplines
totalaveChars = characters/totallines
nonempaveChars = characters/lines
result = (f'{totallines:5} lines in list n'
f'{emplines:5} empty lines in list n'
f'{totalaveChars:5.1f} average characters per line n'
f'{nonempaveChars:5.1f} average chars per non-empty line')
return result
在主程序中,您stats
变量传递给函数infile
,这是一个文件。您无需在统计功能中使用with
重新打开它。此外,with
将确保最后关闭。因此,在您的主循环中,infile
在调用stats
后关闭。
尝试以下操作;
def copy_file():
infile_name = input("Please enter the name of the file to copy: ")
parameter = input("Please enter a parameter(line numbers, Gutenberg trim, statistics, none): ")
outfile_name = input("Please enter the name of the new copy: ")
counter = 1
with open(infile_name, 'r', encoding='utf8') as infile:
with open(outfile_name, 'w', encoding='utf8') as outfile:
if parameter == 'line numbers':
for line in infile:
outfile.write(f' {counter:6}: {line}')
counter += 1
elif parameter == 'Gutenberg trim':
copyStart = False
for line in infile:
#print(line.strip())
if '*** START' in line.strip():
copyStart = True
continue
elif '*** END' in line.strip():
copyStart = False
break
if copyStart == True:
outfile.write(line)
elif parameter == 'statistics':
outfile.write(stats(infile))
for line in infile:
outfile.write(line)
else:
for line in infile:
outfile.write(line)
copy_file()
使用with open(filename, 'r') as file:
它将在操作完成后自动关闭文件,而不是之前。
elif parameter == 'statistics': outfile.write(stats(infile)) for line in infile: outfile.write(line)
。只有统计信息进入,而不是其余内容 原始文件...
我有根据的猜测是stats
函数消耗并且可能 关闭输入流 (IS(。
如果stats
以某种方式表现良好并限制自己消费 是的,可以倒带
...
infile.seek(0) # rewind the input stream
for line in infile:
outfile.write(line)
另一方面,如果stats
有点破坏性并关闭 总之,IS 可以使用文件对象的.name
属性 重新打开它,就像这样
...
for line in open(infile.name):
outfile.write(line)
第二种解决方案即使在第一种较温和的假设和 即使代码infile
是从 外部调用。
另一种可能性,如果可以访问和修改stats
源 代码,是撤消函数执行的读取,记忆 任何read
操作之前输入流中的当前位置 然后将 IS 倒回该位置
def stats(infile):
...
current_pos = infile.tell()
# do your stuff
...
infile.seek(current_pos)
return workload
当然,要使其正常工作,文件对象不必关闭 在.seek()
之前,要么明确(通过.close()
(或 隐式(落入with
块的范围之外(。
如果这是您的情况(已关闭的文件(,请删除 明确的infile.close()
或(不必要的(with
声明,以及 倒带将是正确的。