subprocess.PIPE 防止可执行文件关闭

subprocess.PIPE prevents executable from closing

为什么 subprocess.PIPE 阻止被调用的可执行文件关闭。

我使用以下脚本来调用具有多个输入的可执行文件:

import subprocess, time

CREATE_NO_WINDOW = 0x08000000
my_proc = subprocess.Popen("myApp.exe " + ' '.join([str(input1), str(input2), str(input3)]),
                            startupinfo=subprocess.STARTUPINFO(), stdout=subprocess.PIPE,
                            creationflags = CREATE_NO_WINDOW)

然后我监视应用程序是否在给定时间(300 秒)内完成,如果没有,我就将其终止。我还阅读了应用程序的输出以了解它是否未能完成所需的任务。

proc_wait_time = 300
start_time = time.time()
sol_status = 'Fail'
while time.time() - start_time < proc_wait_time:
    if (my_proc.poll() is None):
        time.sleep(1)
    else:
        try:
            sol_status = my_proc.stdout.read().replace('\r\n \r\n','')
            break
        except:
            sol_status = 'Fail'
            break
else:
    try: my_proc.kill()
    except: None
    sol_status = 'Frozen'

if sol_status in ['Fail', 'Frozen']:
    print ('Failed running my_proc')

正如您从代码中注意到的那样,我需要等待 myApp.exe 完成,但是,有时 myApp.exe 会冻结。由于上面的脚本是循环的一部分,我需要识别这种情况(通过计时器),跟踪它并杀死 myApp.exe 这样整个脚本就不会卡住!

现在,问题是如果我使用 subprocess.PIPE(如果我想读取应用程序的输出,我想我必须这样做)然后 myApp.exe 在完成后不会关闭,因此my_proc.poll() is None 始终为真。

我正在使用 Python 2.7.

有一个管道缓冲区 limit/bug 以防大量数据写入 subprocess.PIPE。修复它的最简单方法是将数据直接通过管道传输到文件中:

_stdoutHandler = open('C:/somePath/stdout.log', 'w')
_stderrHandler = open('C:/somePath/stderr.log', 'w')

my_proc = subprocess.Popen(
    "myApp.exe " + ' '.join([str(input1), str(input2), str(input3)]),  
    stdout=_stdoutHandler, 
    stderr=_stderrHandler, 
    startupinfo=subprocess.STARTUPINFO(), 
    creationflags=CREATE_NO_WINDOW
)
...
_stdoutHandler.close()
_stderrHandler.close()