我的文件在 .write() 之后不断关闭

  • 本文关键字:之后 文件 write python
  • 更新时间 :
  • 英文 :


这是我试图完成的这段代码:

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声明,以及 倒带将是正确的。

最新更新