在 Python 的 Spyder 中,将控制台打印到日志文件是不可逆的
Printing the console to a log file is not reversible in Spyder for Python
我正在为 Python 使用 Spyder,有时我想将控制台打印到日志文件中(在输出很长的情况下),有时我只想在控制台上输出.为此,我在 Python 文件中使用了以下结构:
文件开头:
import sys
# specify if the output should be printed on a separate log file or on the console
printLogToFile = False
if printLogToFile == True:
#Specify output file for the logs
sys.stdout = open('C:/Users/User 1/logfile.txt', 'w')
文件末尾:
# Close the log file if output is printed on a log file and not on the console
if printLogToFile == True:
sys.stdout.close()
sys.stdout = sys.__stdout__
基本上,每当我的布尔变量 printLogToFile
的值为 False 时,所有内容都会按应有的方式打印在控制台上,只要它的值为 True,所有内容都会打印到日志文件中。但是,一旦我 运行 仅一次带有 printLogToFile=True
的文件,这就不能再逆转了。即使变量的值为 False,它仍然会将所有内容打印到日志文件中,而不是打印到控制台上。更奇怪的是,对于与此文件没有任何关联的其他 Python 文件,控制台也不再打印到控制台上。解决此问题的唯一方法是关闭 Spyder 并重新启动它。
您是否知道为什么会发生这种情况以及如何避免这种情况?我会很感激每一条评论。
Spyder 中的控制台是一个 IPython 控制台,而不是一个普通的 Python 控制台,所以我认为 IPython 正在使用 stdout
做一些事情,这会导致你的方法失败。
docs for sys.__stdout__
说
It can also be used to restore the actual files to known working file
objects in case they have been overwritten with a broken object.
However, the preferred way to do this is to explicitly save the
previous stream before replacing it, and restore the saved object.
换句话说,试试:
if printLogToFile:
prev_stdout = sys.stdout
sys.stdout = open('C:/Users/User 1/logfile.txt', 'w')
# code that generates the output goes here
if printLogToFile:
sys.stdout.close()
sys.stdout = prev_stdout
作为替代方案,基于 this answer and assuming Python >= 3.7, you can use contextlib 和 with
语句来选择性地捕获某些代码的输出。这似乎适用于 Spyder 4 和 5:
from contextlib import redirect_stdout, nullcontext
if printLogToFile:
f = open('myfile.txt', 'w')
cm = redirect_stdout(f)
else:
cm = nullcontext()
with cm:
# code that generates the output goes here
如果您想执行整个 Python 脚本 myscript.py
并捕获它输出的所有内容,可能更容易保持脚本不变并从包装脚本调用它:
# put this in the same folder as myscript.py
from contextlib import redirect_stdout
with redirect_stdout(open('myfile.txt', 'w')):
import myscript
如果您想要比这更灵活的东西,可能是时候开始使用 logging。
我正在为 Python 使用 Spyder,有时我想将控制台打印到日志文件中(在输出很长的情况下),有时我只想在控制台上输出.为此,我在 Python 文件中使用了以下结构:
文件开头:
import sys
# specify if the output should be printed on a separate log file or on the console
printLogToFile = False
if printLogToFile == True:
#Specify output file for the logs
sys.stdout = open('C:/Users/User 1/logfile.txt', 'w')
文件末尾:
# Close the log file if output is printed on a log file and not on the console
if printLogToFile == True:
sys.stdout.close()
sys.stdout = sys.__stdout__
基本上,每当我的布尔变量 printLogToFile
的值为 False 时,所有内容都会按应有的方式打印在控制台上,只要它的值为 True,所有内容都会打印到日志文件中。但是,一旦我 运行 仅一次带有 printLogToFile=True
的文件,这就不能再逆转了。即使变量的值为 False,它仍然会将所有内容打印到日志文件中,而不是打印到控制台上。更奇怪的是,对于与此文件没有任何关联的其他 Python 文件,控制台也不再打印到控制台上。解决此问题的唯一方法是关闭 Spyder 并重新启动它。
您是否知道为什么会发生这种情况以及如何避免这种情况?我会很感激每一条评论。
Spyder 中的控制台是一个 IPython 控制台,而不是一个普通的 Python 控制台,所以我认为 IPython 正在使用 stdout
做一些事情,这会导致你的方法失败。
docs for sys.__stdout__
说
It can also be used to restore the actual files to known working file objects in case they have been overwritten with a broken object. However, the preferred way to do this is to explicitly save the previous stream before replacing it, and restore the saved object.
换句话说,试试:
if printLogToFile:
prev_stdout = sys.stdout
sys.stdout = open('C:/Users/User 1/logfile.txt', 'w')
# code that generates the output goes here
if printLogToFile:
sys.stdout.close()
sys.stdout = prev_stdout
作为替代方案,基于 this answer and with
语句来选择性地捕获某些代码的输出。这似乎适用于 Spyder 4 和 5:
from contextlib import redirect_stdout, nullcontext
if printLogToFile:
f = open('myfile.txt', 'w')
cm = redirect_stdout(f)
else:
cm = nullcontext()
with cm:
# code that generates the output goes here
如果您想执行整个 Python 脚本 myscript.py
并捕获它输出的所有内容,可能更容易保持脚本不变并从包装脚本调用它:
# put this in the same folder as myscript.py
from contextlib import redirect_stdout
with redirect_stdout(open('myfile.txt', 'w')):
import myscript
如果您想要比这更灵活的东西,可能是时候开始使用 logging。