简体   繁体   English

在 Python 的 Spyder 中,将控制台打印到日志文件是不可逆的

[英]Printing the console to a log file is not reversible in Spyder for Python

I am using Spyder for Python and sometime I would like to print the console into a log file (in cases where the output is quite long) and sometimes I just want to have the output at the console.我正在使用 Python 的 Spyder,有时我想将控制台打印到日志文件中(在输出很长的情况下),有时我只想在控制台上输出。 For this purpose I use the following construction in my Python files:为此,我在 Python 文件中使用以下结构:

In the beginning of the file:在文件的开头:

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')

At the end of the file:在文件末尾:

# 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__

Basically, whenever my boolean variable printLogToFile has the value False then everything is printed on the console as it should and whenever it has the value True everything is printed into the logfile.基本上,每当我的布尔变量printLogToFile的值为 False 时,所有内容都会按原样打印在控制台上,并且每当它的值为 True 时,所有内容都会打印到日志文件中。 However, once I run just once the file with printLogToFile=True this can't be reversed any longer.但是,一旦我只运行一次带有printLogToFile=True的文件, printLogToFile=True逆转了。 Even when the variable has the value False it still prints everything into the log file and not onto the console.即使变量的值为 False,它仍然会将所有内容打印到日志文件中,而不是打印到控制台上。 What is even more strange is that also for other Python files, that do not have any connection to this file, the console is not printed any longer onto the console.更奇怪的是,对于与此文件没有任何连接的其他 Python 文件,控制台不再打印到控制台上。 The only way to solve this problem is to close Spyder and restart it again.解决这个问题的唯一方法是关闭Spyder并重新启动它。

Do you have any idea why this is happening and how to avoid this?您知道为什么会发生这种情况以及如何避免这种情况吗? I'd appreciate every comment.我会很感激每一条评论。

The console in Spyder is an IPython console, not a plain Python console, so I think IPython is doing something with stdout that causes your approach to fail. Spyder 中的控制台是一个IPython控制台,而不是一个普通的 Python 控制台,所以我认为 IPython 正在使用stdout做一些导致您的方法失败的事情。

The docs for sys.__stdout__ say 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.但是,执行此操作的首选方法是在替换之前显式保存先前的流,并恢复保存的对象。

In other words, try:换句话说,尝试:

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

As an alternative, based on this answer and this answer assuming Python >= 3.7, you can use contextlib and a with statement to selectively capture the output of some of your code.作为替代方案,基于此答案此答案假设 Python >= 3.7,您可以使用contextlibwith语句有选择地捕获某些代码的输出。 This seems to work for me in Spyder 4 and 5:这在 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

If you want to execute the whole of your Python script myscript.py and capture everything it outputs, it's probably easier to leave your script unmodified and call it from a wrapper script:如果您想执行整个 Python 脚本myscript.py并捕获它输出的所有内容, 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
 

If you want anything more flexible than that, it's probably time to start using logging .如果你想要比这更灵活的东西,可能是时候开始使用logging 了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM