临时修改sys.stdout报错ValueError:对已关闭文件执行I/O操作
解决「ValueError: I/O operation on closed file」报错问题
咱们来拆解一下你遇到的问题,先看你执行的代码:
>>> import sys >>> sys.stdout = open('myfile.log', 'w') >>> print('escribo en el archivo log...') >>> print('todavia en el archivo log...') >>> sys.stdout.close() >>> open('myfile.log').read()
报错原因分析
你看到的这个报错,并不是最后一行open('myfile.log').read()导致的,而是在你执行sys.stdout.close()之后,Python的交互式环境(也就是你用的命令行shell)尝试向标准输出(stdout)写入下一个提示符>>>,但此时你已经把sys.stdout指向的文件对象关闭了,这就触发了「对已关闭文件执行I/O操作」的错误。
简单来说:你替换了默认的stdout为自定义的文件,关闭这个文件后,系统再想往stdout写东西(比如命令提示符)就失败了。
关于Python版本差异的疑问
这个问题和Python 3.4与3.6.5的版本差异完全无关——在这两个版本的交互式环境中,这个行为是一致的,都会出现同样的报错。
修复方案
手动恢复原stdout
在关闭自定义的stdout文件之前,先保存并恢复原来的标准输出对象:
>>> import sys >>> # 先保存原始的stdout对象 >>> original_stdout = sys.stdout >>> sys.stdout = open('myfile.log', 'w') >>> print('escribo en el archivo log...') >>> print('todavia en el archivo log...') >>> # 先关闭文件,再恢复stdout >>> sys.stdout.close() >>> sys.stdout = original_stdout >>> # 现在执行读取操作就不会报错了 >>> open('myfile.log').read() 'escribo en el archivo log...\ntodavia en el archivo log...\n'
更优雅的上下文管理器方式
使用contextlib.redirect_stdout可以自动帮你处理stdout的恢复,避免手动操作出错:
from contextlib import redirect_stdout with open('myfile.log', 'w') as log_file: with redirect_stdout(log_file): print('escribo en el archivo log...') print('todavia en el archivo log...') # 退出with代码块后,stdout会自动恢复为默认值 print("现在又可以正常在控制台输出了") print("读取日志内容:", open('myfile.log').read())
内容的提问来源于stack exchange,提问作者FedePython
相关产品推荐
相关产品推荐

