使用 subprocess.Popen 在 Windows 中启动程序 - 子进程有时会卡住 - 我的脚本稳定吗?

问题描述

作为 Python (3.8.2) 脚本的一部分,我通过命令行在 Windows (10) 中启动了一个程序。该程序运行模拟、导出数据并关闭。我的脚本这样做了数百次。偶尔,cmd 窗口出现但什么也不显示(Windows 程序似乎没有做任何事情)。我正在尝试确定问题出在外部程序还是我的脚本上。

我已经搜索了其他答案,但事实证明子流程世界很难理解。我使用 Python 来处理一些基本的移动/解释数据。我看到了这个答案 (Understanding Popen.communicate),其中包括

注意:如果读/写不同步,这是一个非常脆弱的代码;它 死锁。

这似乎很相关,但我无法理解和实施它。

我的功能是:

def run_program(args):
    cmd = #defined by args
    p = subprocess.Popen(cmd,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
    stdout,stderr = p.communicate()
    variables = #read from some datafiles created by the program that was run
    return variables

子进程卡住有什么明确的原因吗? (我不知道正确的术语是阻塞还是挂起)。

解决方法

一个可行的解决方案,灵感来自How to kill subprocess if no activity in stdout/stderr

def run_program(args,timeout):
    cmd = [] #defined by args
    if timeout == 'default':
        timeout = 600
    tries = 0
    while tries < 4:
        tries += 1
        try:
            p = subprocess.Popen(cmd,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
            t = 0
            while p.poll() != 0:
                if t > timeout:
                    raise RuntimeError('Timeout')
                    break
                time.sleep(1)
                t+=1
            successful = True
        except RuntimeError:
            kill = subprocess.Popen("TASKKILL /F /PID {pid} /T".format(pid=p.pid))
            # some actions for this condition
            successful = False
        if successful == True:
            # some actions for this condition
            break
    return variables,t

我使用 timeout 变量将有关上次运行时间的信息传入/传出函数。