英文:
How to fix "sys.stderr is None" after compiled a script with Pyinstaller --noconsole?
问题
环境
Windows 10
Python 3.10
Pyinstaller 5.9
问题:
我试图编译一个需要在控制台中运行一些命令行以从系统中获取一些值的脚本。
if __name__ == '__main__':
faulthandler.enable()
try:
proc = subprocess.Popen(p_command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
stderr=subprocess.STDOUT, close_fds=True)
output, errors = proc.communicate()
except:
pass
你可以使用上面的代码来重现这个错误。
当我使用控制台编译时,“exe”正常工作。但当我使用“--noconsole”编译时,“exe”失败,并显示以下错误消息:
Traceback (most recent call last):
File "script.py", line 5432, in <module>
faulthandler.enable()
RuntimeError: sys.stderr is None
经过几个小时的调查,我明白了来自代码“subprocess.Popen”的stdin和stdout参数不能与“--noconsole”编译模式一起使用。我尝试了以下解决方案:
stream = io.StringIO()
sys.stdout = stream
sys.stderr = stream
但它仍然不起作用。我验证了文档:
https://readthedocs.org/projects/pyinstaller/downloads/pdf/stable/
它明确指出:
(Windows) 在窗口/无控制台模式下,停止设置sys.stdout和sys.stderr为自定义的NullWriter对象,而是将它们保留为None。这与窗口式Python解释器(pythonw.exe)的行为相匹配,并防止与期望流要么为None,要么为完全与io.IOBase兼容的对象的代码之间的互操作性问题。 (#3503)
所以解决方案N°1似乎是正确的,不是吗?
去年我编译上一个版本时并没有遇到这个问题。我不明白为什么现在会出现这个问题。
请问有没有人对这个问题有解决方案?请帮帮忙。
英文:
ENVIRONMENT
Windows 10
Python 3.10
Pyinstaller 5.9
PROBLEM:
I am trying to compile a script that needs to run some command lines in the console in order to get some values from the system.
if __name__ == '__main__':
faulthandler.enable()
try:
proc = subprocess.Popen(p_command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
stderr=subprocess.STDOUT, close_fds=True)
output, errors = proc.communicate()
except:
pass
You can use this code above to reproduce the error.
When I compile with the console, the "exe" works fine.
When I compile with "--noconsole", the "exe" failed with this error message :
Traceback (most recent call last):
File "script.py", line 5432, in <module>
faulthandler.enable()
RuntimeError: sys.stderr is None
After a few hours of investigation, I've understood the stdin and stdout arguments from the code "subprocess.Popen) can't be used with "--noconsole" compilation mode.
I tried this solution :
stream = io.StringIO()
sys.stdout = stream
sys.stderr = stream
But it still doesn't work.
I verified the doc:
https://readthedocs.org/projects/pyinstaller/downloads/pdf/stable/
It clearly said :
> (Windows) In windowed/noconsole mode, stop setting sys.stdout and
> sys.stderr to custom NullWriter object, and instead leave them at
> None. This matches the behavior of windowed python interpreter
> (pythonw. exe) and prevents interoperability issues with code that
> (rightfully) expects the streams to be either None or objects that are
> fully compatible with io.IOBase. (#3503)
So the solution N°1 seems correct, doesn't it?
I didn't have this issue last year when I compiled the previous version. I don't understand why now there is this issue.
Does anyone have any solution to this issue PLEASE?
答案1
得分: 1
看起来你遇到了一个 RuntimeError 错误,因为 sys.stderr 为 None。faulthandler 模块需要一个有效的 stderr 流来报告错误。这可能发生在你的 Python 脚本在一个未正确设置或丢失标准错误流(sys.stderr)的环境中执行时。
要解决这个问题,你可以尝试以下之一:
在启用 faulthandler 之前设置一个有效的 stderr 流:
import sys
import os
import faulthandler
import subprocess
if sys.stderr is None:
sys.stderr = open(os.devnull, 'w')
if __name__ == '__main__':
faulthandler.enable()
try:
proc = subprocess.Popen(p_command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
output, errors = proc.communicate()
except:
pass
或者,如果你想要查看错误输出,你可以将 sys.stderr 设置为 sys.stdout:
if sys.stderr is None:
sys.stderr = sys.stdout
....
英文:
It seems you are running into a RuntimeError because sys.stderr is None. The faulthandler module needs a valid stderr stream to report errors. This can occur when your Python script is executed in an environment where the standard error stream (sys.stderr) is not properly set up or is missing.
To fix this issue, you can try one of the following:
Set up a valid stderr stream before enabling the faulthandler:
import sys
import os
import faulthandler
import subprocess
if sys.stderr is None:
sys.stderr = open(os.devnull, 'w')
if __name__ == '__main__':
faulthandler.enable()
try:
proc = subprocess.Popen(p_command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
output, errors = proc.communicate()
except:
pass
Alternatively, if you want to see the error output, you can set sys.stderr to sys.stdout:
if sys.stderr is None:
sys.stderr = sys.stdout
....
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论