【发布时间】:2011-02-28 08:43:39
【问题描述】:
我想在多线程python程序的每个线程中执行一个外部程序。
假设最大运行时间设置为 1 秒。如果启动的进程在 1 秒内完成,主程序将捕获其输出以进行进一步处理。如果它没有在 1 秒内完成,主程序将终止它并启动另一个新进程。
如何实现?
【问题讨论】:
标签: python multithreading subprocess
我想在多线程python程序的每个线程中执行一个外部程序。
假设最大运行时间设置为 1 秒。如果启动的进程在 1 秒内完成,主程序将捕获其输出以进行进一步处理。如果它没有在 1 秒内完成,主程序将终止它并启动另一个新进程。
如何实现?
【问题讨论】:
标签: python multithreading subprocess
您可以定期轮询它:
import subprocess, time
s = subprocess.Popen(['foo', 'args'])
timeout = 1
poll_period = 0.1
s.poll()
while s.returncode is None and timeout > 0:
time.sleep(poll_period)
timeout -= poll_period
s.poll()
if timeout <= 0:
s.kill() # timed out
else:
pass # completed
然后您可以将上述内容放入一个函数中并将其作为线程启动。
【讨论】:
这是我使用的辅助函数:
def run_with_timeout(command, timeout):
import time
import subprocess
p = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while timeout > 0:
if p.poll() is not None:
return p.communicate()
time.sleep(0.1)
timeout -= 0.1
else:
try:
p.kill()
except OSError as e:
if e.errno != 3:
raise
return (None, None)
【讨论】:
command 生成大输出(足以填充其操作系统标准输出/标准错误管道缓冲区),它不会返回任何输出。您应该在等待超时时读取输出。 2.(次要细节)如果timeout 很大,那么循环会漂移,因为time.sleep(0.1) 可以睡得少于/多于0.1 秒。你可以改用while endtime > timer():。
在 linux 上的一个讨厌的 hack 是使用 timeout 程序来运行命令。不过,您可以选择更好的全 Python 解决方案。
【讨论】:
这是一个使用pexpect 模块的解决方案(我需要在程序超时之前捕获它的输出,我没有设法用subprocess.Popen 做到这一点):
import pexpect
timeout = ... # timeout in seconds
proc = pexpect.spawn('foo', ['args'], timeout = timeout)
result = proc.expect([ pexpect.EOF, pexpect.TIMEOUT])
if result == 0:
# program terminated by itself
...
else:
# result is 1 here, we ran into the timeout
...
print "program's output:", print proc.before
【讨论】: