运行 在子进程中无法重定向 Pyinstaller 单个可执行文件输出
Cannot redirect Pyinstaller single executable output while running it in subprocess
我已经为此苦苦挣扎了一段时间。我已经设法编写了一个可以捕获 .py
文件的 STDOUT 的代码,但是当我 运行 与从 Pyinstaller 生成的可执行文件完全相同的代码时(不管它是否有窗口) readyReadStandardOutput
信号永远不会出现。
根据我的测试,只有当应用程序崩溃时才会发出任何信号,但是我需要 GUI 和可执行文件之间的实时通信。
这是我的代码供参考:
def start_process(self, program, args=None):
if args is None:
args = []
process = QtCore.QProcess(self)
process.readyReadStandardOutput.connect(partial(self.onReadyReadStandardOutput, self.number_process_running))
process.start(program)
以及我将信号连接到的方法:
def onReadyReadStandardOutput(self, i):
print("called")
process = self.sender()
self.results[i] = process.readAllStandardOutput()
self.resultsChanged.emit(self.results)
我正在 Windows 机器上工作
编辑:最小可重现示例
来个小脚本
import time
if __name__ == "__main__":
num = 0
while True:
num = num + 1
print(num)
time.sleep(3)
让我们暂时离开 PyQT 进程,使用更简单的 Popen。
如果我们 运行 Popen 中的脚本,stdout 将被重定向到调用进程。
if __name__ == '__main__':
p = Popen([r'python', 'test.py'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
while p.poll() is None:
out = p.stdout.readline()
print(out)
但是,如果我们使用第一个脚本并通过 PyInstaller 单个可执行生成器,Popen 将不再捕获任何输出,它只会冻结
import os
import sys
import PyInstaller.__main__
file_location = os.path.dirname(os.path.realpath(__file__))
if sys.platform == "win32":
PyInstaller.__main__.run([
'--name=%s' % 'test',
'--onefile',
'--noconsole',
'--distpath=%s' % os.path.join(file_location, 'dist'),
'--workpath=%s' % os.path.join(file_location, 'build'),
'--specpath=%s' % os.path.join(file_location),
os.path.join(file_location, 'test.py'),
])
所以我的问题又是 - 我是否遗漏了一些重要的部分?或者这可能只是 pyinstaller 的错。
好像编译脚本的时候要把print的flush设置为True,改成:
import time
if __name__ == "__main__":
num = 0
while True:
num = num + 1
print(num, <b>flush=True</b>)
time.sleep(3)
我已经为此苦苦挣扎了一段时间。我已经设法编写了一个可以捕获 .py
文件的 STDOUT 的代码,但是当我 运行 与从 Pyinstaller 生成的可执行文件完全相同的代码时(不管它是否有窗口) readyReadStandardOutput
信号永远不会出现。
根据我的测试,只有当应用程序崩溃时才会发出任何信号,但是我需要 GUI 和可执行文件之间的实时通信。
这是我的代码供参考:
def start_process(self, program, args=None):
if args is None:
args = []
process = QtCore.QProcess(self)
process.readyReadStandardOutput.connect(partial(self.onReadyReadStandardOutput, self.number_process_running))
process.start(program)
以及我将信号连接到的方法:
def onReadyReadStandardOutput(self, i):
print("called")
process = self.sender()
self.results[i] = process.readAllStandardOutput()
self.resultsChanged.emit(self.results)
我正在 Windows 机器上工作
编辑:最小可重现示例
来个小脚本
import time
if __name__ == "__main__":
num = 0
while True:
num = num + 1
print(num)
time.sleep(3)
让我们暂时离开 PyQT 进程,使用更简单的 Popen。 如果我们 运行 Popen 中的脚本,stdout 将被重定向到调用进程。
if __name__ == '__main__':
p = Popen([r'python', 'test.py'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
while p.poll() is None:
out = p.stdout.readline()
print(out)
但是,如果我们使用第一个脚本并通过 PyInstaller 单个可执行生成器,Popen 将不再捕获任何输出,它只会冻结
import os
import sys
import PyInstaller.__main__
file_location = os.path.dirname(os.path.realpath(__file__))
if sys.platform == "win32":
PyInstaller.__main__.run([
'--name=%s' % 'test',
'--onefile',
'--noconsole',
'--distpath=%s' % os.path.join(file_location, 'dist'),
'--workpath=%s' % os.path.join(file_location, 'build'),
'--specpath=%s' % os.path.join(file_location),
os.path.join(file_location, 'test.py'),
])
所以我的问题又是 - 我是否遗漏了一些重要的部分?或者这可能只是 pyinstaller 的错。
好像编译脚本的时候要把print的flush设置为True,改成:
import time
if __name__ == "__main__":
num = 0
while True:
num = num + 1
print(num, <b>flush=True</b>)
time.sleep(3)