【问题标题】:subprocess.PIPE prevents executable from closingsubprocess.PIPE 阻止可执行文件关闭
【发布时间】:2021-06-14 05:34:50
【问题描述】:

为什么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 总是 True .

我使用的是 Python 2.7。

【问题讨论】:

  • 杀死应用程序时是否正在关闭管道?
  • 不,这都是在my_proc 方面,我怎样才能显式关闭 PIPE?我需要在kill() 之后立即执行吗?我一直认为这是集成在kill 中的。另外,如何解决my_proc.poll() is None一直为真的问题?
  • 如果您不是从管道读取数据,并且进程向其写入的数据超过缓冲区(可能是 4K),那么它将阻塞,直到一些缓冲区空间可用 - 这永远不会发生.
  • @jasonharper 那么解决方法是stdout.read() 每隔一段时间就合并一次吗?
  • @Mosy:stderr 有什么东西吗? returncode 呢?如果您使用 subprocess.Popen('taskkill /F /T /PID %i' % my_proc.pid) 而不是 my_proc.kill() 会发生什么?将标准输出直接通过管道传输到文件中:subprocess.Popen("myApp.exe, ..., stdout=open("C:/temp/whatever.log", 'w').open())

标签: python python-2.7 subprocess


【解决方案1】:

在向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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-27
    • 2019-10-04
    • 1970-01-01
    • 2020-09-26
    • 2017-01-21
    • 1970-01-01
    • 2012-11-09
    相关资源
    最近更新 更多