[英]Show stdout with PyInstaller noconsole
How can I create a GUI application that also provides a CLI without having a popup shell using PyInstaller?如何使用 PyInstaller 创建一个也提供 CLI 的 GUI 应用程序,而不会弹出shell?
For example, if I create the following application with pyinstaller argparse_gui.py --noconsole
, stdout isn't displayed in the shell:例如,如果我使用
pyinstaller argparse_gui.py --noconsole
创建以下应用程序,则标准输出不会显示在 shell 中:
C:\projects\argparse_gui\dist\argparse_gui>argparse_gui.exe -V
C:\projects\argparse_gui\dist\argparse_gui>
I can redirect stdout/stderr to a file with argparse_gui.exe -V > log.txt 2>&1
, but that's not exactly user-friendly.我可以使用
argparse_gui.exe -V > log.txt 2>&1
将 stdout/stderr 重定向到一个文件,但这并不完全是用户友好的。 I can see stdout if built without --noconsole
, but then there's a nagging separate shell window.如果在没有
--noconsole
的情况下构建,我可以看到标准输出,但是还有一个令人讨厌的单独 shell window。
# argparse_gui.py
import sys
import argparse
from PyQt5 import QtCore, QtWidgets, QtGui
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.init_widgets()
self.init_layout()
def init_widgets(self):
self.label = QtWidgets.QLabel('Hello, world!')
def init_layout(self):
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
centralWidget = QtWidgets.QWidget()
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-V", "--version", help="display application information", action='store_true')
args = parser.parse_args()
if args.version:
print('Version 123', flush=True)
else:
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
EDIT: I found a roundabout way to do it, but the console window appears until the GUI loads up.编辑:我找到了一种迂回的方法,但控制台 window 会出现,直到 GUI 加载。 I placed the following code at the top of my main script and ran Pyinstaller without --windowed.
我将以下代码放在主脚本的顶部,并在没有 --windowed 的情况下运行 Pyinstaller。 This hides the console window if the script isn't run from an existing console.
如果脚本不是从现有控制台运行的,这将隐藏控制台 window。
import ctypes
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
process_array = (ctypes.c_uint8 * 1)()
num_processes = kernel32.GetConsoleProcessList(process_array, 1)
if num_processes < 3: ctypes.WinDLL('user32').ShowWindow(kernel32.GetConsoleWindow(), 0)
Otherwise, I'm going to conclude that there isn't a way using PyInstaller.否则,我将得出结论,没有办法使用 PyInstaller。 The EXE is bundled with
pythonw
if --noconsole/--windowed.如果 --noconsole/--windowed,则 EXE 与
pythonw
捆绑在一起。 PythonW doesn't have a console attached, even if launched from the console. PythonW 没有附加控制台,即使从控制台启动。
Command line arguments are still passed, however.然而,命令行 arguments 仍然通过。 You can still use sys.argv or argparser to access them.
您仍然可以使用 sys.argv 或 argparser 来访问它们。
When running in --noconsole
, sys.stdout
is a NullWriter
object and sys.__stdout__
is None
.在
--noconsole
中运行时, sys.stdout
是NullWriter
object 并且sys.__stdout__
是None
。 Using open()
on 1 raises an exception, CON and CONOUT$ fail to do anything.在 1 上使用
open()
会引发异常,CON 和 CONOUT$ 无法执行任何操作。 Redirecting the console to >&1 throws an error.将控制台重定向到 >&1 会引发错误。
Note: Under some conditions stdin, stdout and stderr as well as the original values stdin , stdout and stderr can be None.
注意:在某些情况下,stdin、stdout 和 stderr 以及原始值stdin 、 stdout和stderr可以为 None。 It > is usually the case for Windows GUI apps that aren't connected to a console and Python apps started with pythonw.
对于未连接到控制台的 Windows GUI 应用程序和使用 pythonw 启动的 Python 应用程序通常是这种情况。 https://docs.python.org/3/library/sys.html#sys.__stderr __
https://docs.python.org/3/library/sys.html#sys.__stderr __
Pyinstaller explicitly uses PythonW.exe if the EXE is built with --noconsole.如果 EXE 是使用 --noconsole 构建的,那么 Pyinstaller 会显式使用 PythonW.exe。 I wasn't able to find a way around this, such as loading the console bootloader if called from the cli but pythonw otherwise.
我无法找到解决此问题的方法,例如如果从 cli 调用,则加载控制台引导加载程序,否则加载 pythonw。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.