【问题标题】:How to keep subprocess.Popen console open after crashing on Windows?在 Windows 上崩溃后如何保持 subprocess.Popen 控制台打开?
【发布时间】:2016-02-12 08:05:53
【问题描述】:

我的目标是为每个Popen 进程使用几个不同的参数调用主程序,每个进程都有自己的控制台窗口。但是,一旦遇到崩溃,它就会关闭该控制台,而我真的很想保持打开状态。

import subprocess
from subprocess import CREATE_NEW_CONSOLE
import time

for i in range(1, 5):
    subprocess.Popen(["python", "main.py", str(i), str(i)], close_fds=False, creationflags=CREATE_NEW_CONSOLE)
    time.sleep(3)

是否可以使用subprocess.Popen 创建一个新进程并保持控制台打开以便我读取错误? 链接到subprocess docs

【问题讨论】:

    标签: windows python-3.x console popen


    【解决方案1】:

    控制台窗口由 ​​conhost.exe (Win 7+) 的实例托管,当没有附加进程时退出。因此,您只需将第二个 python.exe 进程附加到每个控制台并等待它。这是一个简单的演示脚本,它使服务员进程等待主进程(即工作进程的父进程):

    import sys
    
    # If started with a pid, wait for the associated process to exit.
    if len(sys.argv) > 1:
        import ctypes
        kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
        SYNCHRONIZE = 0x00100000
        pid = int(sys.argv[1])
        hproc = kernel32.OpenProcess(SYNCHRONIZE, 0, pid)
        if not hproc:
            sys.exit(ctypes.get_last_error())
        print('waiter: waiting')
        kernel32.WaitForSingleObject(hproc, -1)
        sys.exit(0)
    
    import os
    import subprocess
    print('worker: start')
    # The waiter waits on our parent (ppid).
    p = subprocess.Popen([sys.executable, sys.argv[0], str(os.getppid())])
    print('worker: exit')
    

    例如:

    >>> import sys, subprocess
    >>> flags = subprocess.CREATE_NEW_CONSOLE
    >>> p = subprocess.Popen([sys.executable, 'main.py'], creationflags=flags)
    >>> p.wait()
    0
    >>> exit()
    

    工作进程重新生成自己以等待其父进程。然后它以返回码 0 退出。控制台窗口在 exit() 之后关闭。

    您还可以从主进程生成服务员实例。在这种情况下,将工作人员的 PID 传递给服务员。然后服务员可以调用FreeConsoleAttachConsole 将自己附加到工作人员的控制台。这比较复杂,但它可以让主进程轻松终止服务员。

    【讨论】:

    • 看起来很复杂。 cmd /k "python main.py {i} {i} && exit 0"(+/-转义)有什么问题吗?
    • 感谢您解决我的问题。经测试,运行良好。虽然,Python C 扩展和 C++ 和 Windows 编程是,我现在不擅长,所以我猜是为了未来。
    • @J.F.Sebastian,你可以这样做,但是等待或终止工作进程会更复杂,因为你有 cmd.exe 而不是 python.exe 的句柄。加上我展示的方式保证所有控制台都与主进程一起退出。使用 cmd.exe 的实例,您必须使用 Job 对象来完成。
    • @eryksun:等待有多复杂?您使用p.wait() 等待cmd 进程。成功时它会自行退出。失败时,据我所知,OP 不想以编程方式终止它(“我真的很想保持打开状态”)。无论如何,终止它不应该比任何可能产生其他进程的进程更复杂(我没有看到main.py 不能依次使用子进程的限制)。
    • @JFSebastian,在我看来,ivarsj10s 只是希望控制台窗口保持打开状态以进行调试(不是一个很好的设计,但我只是在回答手头的问题),我认为它会方便不必手动关闭它们。在我的示例中,当主进程退出或终止时,所有服务员也会退出并且控制台窗口会自动关闭。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 1970-01-01
    • 2014-04-20
    相关资源
    最近更新 更多