【问题标题】:Application called with Subprocess from PySide GUI application (py2exe) stopped working从 PySide GUI 应用程序 (py2exe) 调用子进程的应用程序停止工作
【发布时间】:2015-09-16 07:26:12
【问题描述】:

该程序的体系结构由一个 PySide GUI 可执行文件组成,它使用 Py2exe 构建。此外,它还有一个使用 Py2exe 构建的第二个 python 控制台应用程序。

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

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

如果执行 GUI 应用程序和控制台应用程序(在构建到 Py2exe 应用程序之前),一切都会按预期工作。 如果应用程序是使用 Py2exe 构建的,则外部 Windows 应用程序会冻结并弹出窗口错误。 (应用程序停止工作)

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

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

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

有人问我一个最小的例子。问题是该架构并没有真正允许最小的工作示例。我尽了最大努力,我希望给定的示例能更清楚地描述问题。如解释 通过测试问题可以简化为py2exe。一旦 GUI 应用程序被“编译”以启动控制台应用程序内的非阻塞应用程序,但新应用程序会导致 Windows 错误。

小例子:

控制台应用程序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:

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']
)

【问题讨论】:

  • 请考虑添加minimal reproducible example。我怀疑任何人都会有任何建议,除非您提供一些演示问题的代码(还包括有关您如何使用 py2exe 的详细信息)。

标签: python-2.7 subprocess pyside py2exe nonblocking


【解决方案1】:

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

子进程模块提供了一个参数close_fds来防止子进程继承父进程的句柄。这不适用于我的应用程序。尽管如此,它必须与py2exe有关。

将 DETACHED_PROCESS 标志赋予参数 creationflags 一个新的控制台被打开并且进程成功启动了!

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

工作示例:

import subprocess

DETACHED_PROCESS = 0x00000008

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    • 2021-10-30
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多