使用PySide GUI应用程序(py2exe)的Subprocess调用的应用程序停止工作

时间:2015-09-16 07:26:12

标签: python-2.7 subprocess pyside py2exe nonblocking

该程序的体系结构由PySide构建,使用Py2exe构建。此外,它还有一个使用Py2exe构建的第二个python控制台应用程序。

GUI-App使用命名管道启动控制台应用程序,以便能够发送CTRL_C并捕获stdout / stderr。这是使用pywin32模块完成的。

在控制台应用程序内部,使用子进程模块以阻塞模式执行其他几个Windows应用程序。现在控制台应用程序被一些代码扩展,以非阻塞模式执行另一个程序。

如果执行GUI应用程序和控制台应用程序(在构建到Py2exe应用程序之前),一切都按预期工作并且需要。 如果使用Py2exe构建应用程序,外部Windows应用程序将冻结并弹出Windows错误。 (申请停止工作)

如果外部Windows应用程序的执行代码被隔离并且构建了py2exe可执行文件,那么一切正常。

所以问题必须是py2exe并从GUI应用程序调用控制台应用程序。

我希望有人能指出我正确的方向。

我被要求提供一个最小的例子。问题是该架构并不真正允许一个最小的工作示例。我尽我所能,我希望给定的例子能够更清楚地了解问题。如上所述 通过测试问题可以减少到py2exe。一旦GUI应用程序被编译"在控制台应用程序内启动非阻塞应用程序,但新应用程序导致Windows错误。

最小例子:

Console App console.py:

import logging
import subprocess
from time import sleep

def exec_program_nonblocking(args, cwd=None):
    if cwd:
        logging.debug("Change working directory to: %s", cwd)

    subprocess.Popen(args,
                 cwd=cwd,
                 universal_newlines=True)

def main():
    args = ["program.exe", "arg1", "arg2"]
    exec_program_nonblocking(args)
    while (True):
        print "do something \n"
        sleep(5)

if __name__ == '__main__':      
    main()

setup.py for console App:

from distutils.core import setup
import py2exe

setup(console=['console.py'])

PySide GUI应用程序gui_app.py:

from PySide.QtGui import QApplication

def start_console_app():
    pass
    # complex implementation of openening named pipe,
    # handling callbacks, allowing to send CTRL_C to new process etc.
    # Minimal example is not possible...

app = QtGui.QApplication([])

button = QtGui.QPushButton('Start Console App')
button.clicked.connect(start_console_app)
button.show()

app.exec_()

GUI应用程序的setup.py:

from distutils.core import setup
import py2exe

setup(
    options = {
        'py2exe' : {
            'packages' : 'encodings',
            'unbuffered' : True
            #dll_excludes....
        }
    },
    zipfile = None,

    windows = ['gui_app.py']
)

1 个答案:

答案 0 :(得分:0)

对我来说,here发布的解决方案对我有用。不知何故py2exe与从父进程GUI应用程序传递到子子进程的句柄混乱。对于来自控制台应用程序的子进程的所有可执行文件,它甚至不会发生。

子进程模块提供参数 close_fds ,以防止子进程从父进程中提取句柄。这对我的申请不起作用。它仍然必须与py2exe相关。

将DETACHED_PROCESS标志提供给参数 creationflags ,打开一个新的控制台并成功启动该过程!

唯一的缺点是,据我所知,stdout / stderr无法捕获。

工作示例:

import subprocess

DETACHED_PROCESS = 0x00000008

subprocess.Popen(args,
                 cwd=cwd,
                 creationflags=DETACHED_PROCESS)