gpt4 book ai didi

python - 不稳定的 Popen 管道

转载 作者:太空宇宙 更新时间:2023-11-03 18:06:43 25 4
gpt4 key购买 nike

我想使用subprocess.Popen来运行一个进程,具有以下要求。

  1. 我想在进程运行时将 stdoutstderr 通过管道传回 Popen 的调用者。

  2. 如果进程仍在运行,我想在 timeout 秒后终止该进程。

我得出的结论是,subprocess API 中的缺陷意味着它无法同时满足这两个要求。考虑以下玩具程序:

闲聊.py

while True:
print 'Hi'

沉默.py

while True:
pass

来电者.py

import subprocess
import time

def go(command, timeout=60):
proc = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
start = time.time()
while proc.poll() is None:
print proc.stdout.read(1024) # <----- Line of interest
if time.time() - start >= timeout:
proc.kill()
break
else:
time.sleep(1)

考虑上面标记的线。

  • 如果包含它,go('pythonsilence.py') 将永远挂起 - 而不是仅仅 60 秒 - 因为 read 是一个阻塞调用直到 1024 字节或流结束,但两者都没有出现。

  • 如果加了注释,go('python chatty.py')会一遍遍打印出'Hi',但是怎么可能呢生成时就流回吗? proc.communicate() 阻塞直到流结束。

我很高兴有一个解决方案,将上面的要求 (1) 替换为“在没有发生超时的情况下,我想要获取 stdoutstderr一旦算法完成。”即使这样也存在问题。我的实现尝试如下。

语音.py

for i in xrange(0, 10000):
print 'Hi'

来电者2.py

import subprocess
import time

def go2(command, timeout=60):
proc = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
start = time.time()
while True:
if proc.poll() is not None:
print proc.communicate()
break
elif time.time() - start >= timeout:
proc.kill()
break
else:
time.sleep(1)

但即使这样仍然存在问题。尽管 pythonpeech.py​​ 运行只需几秒钟,但 go2('pythonpeech.py​​') 却需要整整 60 秒。这是因为在 speech.py​​ 中对 print 'Hi' 的调用处于阻塞状态,直到进程被终止时调用 proc.communicate() 。由于 proc.stdout.read 之前用 silence.py 演示过这个问题,所以我真的不知道如何让它工作。

如何同时获取 stdoutstderr 以及超时行为?

最佳答案

诀窍是设置一个边带计时器来终止该进程。我写了一个介于闲聊和沉默之间的程序:

import time
import sys

for i in range(10,0,-1):
print i
time.sleep(1)

然后是一个提前终止它的程序:

import subprocess as subp
import threading
import signal

proc = subp.Popen(['python', 'longtime.py'], stdout=subp.PIPE,
stderr=subp.PIPE)
timer = threading.Timer(3, lambda proc: proc.send_signal(signal.SIGINT),
args=(proc,))
timer.start()
out, err = proc.communicate()
timer.cancel()
print proc.returncode
print out
print err

它的输出:

$ python killer.py
1
10
9
8

Traceback (most recent call last):
File "longtime.py", line 6, in <module>
time.sleep(1)
KeyboardInterrupt

你的计时器可以做得更奇特,比如尝试越来越糟糕的信号直到过程完成,但你明白了。

关于python - 不稳定的 Popen 管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26747500/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com