cx_freeze后subprocess.Popen的行为

3 投票
1 回答
1274 浏览
提问于 2025-04-18 09:21

我有一些Python代码,使用了subprocess.Popen来打开一个控制台应用程序,并获取它的标准输出和错误输出。

在解释器中启动这个程序一切正常,效果也如我所期待的那样。

但是,当我使用cx_freeze并加上--base-name Win32GUI这个选项后,Popen就会在一个控制台窗口中弹出来,这样我就无法捕获标准输出和错误输出了。如果我去掉--base-name Win32GUI,它又能正常工作,但这时我的界面后面会有一个控制台窗口。

这是我的代码(我试过不使用startupinfo和不设置shell=False):

startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
subprocess.Popen(['exe', 'arg1', 'arg2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, startupinfo=startupinfo)

我使用out, err = p.communicate()来获取标准输出和错误输出。

1 个回答

4

好的,我找到了解决办法。看起来因为这是一个Windows的图形界面应用,所以标准输出的句柄不存在,而子进程似乎也继承了这个特性。所以,有一个简单的解决方法和一个稍微复杂一点的方法,后者涉及到win32api和创建一个管道(我没有尝试这个方法)。

以下是最终有效的代码:

startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
stdout_file = tempfile.NamedTemporaryFile(mode='r+', delete=False)
process = subprocess.Popen(['exe', 'arg1', 'arg2'], stdin=subprocess.PIPE, stdout=stdout_file, stderr=subprocess.PIPE, shell=False, startupinfo=startupinfo)
return_code = process.wait()
stdout_file.flush()
stdout_file.seek(0) # This is required to reset position to the start of the file
out = stdout_file.read()
stdout_file.close()

撰写回答