2010-06-06 64 views
4

我想在多线程python程序的每个线程中执行一个外部程序。以指定的最大运行时间运行外部程序

假设最大运行时间设置为1秒。如果启动的过程在1秒内完成,主程序将捕获其输出以供进一步处理。如果它在1秒内没有完成,主程序只是终止它并开始另一个新进程。

如何实现这个?

+0

相关:[子带超时](http://stackoverflow.com/q/1191374/4279) – jfs 2015-01-06 06:59:03

+0

相关:[停止读在Python过程输出,而不挂?](HTTP: //stackoverflow.com/a/4418891/4279) – jfs 2015-01-06 06:59:48

回答

6

你可以定期轮询:

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 

然后,您可以只把上面的功能,并启动它作为一个线程。

+0

它不会捕获孩子的输出。 – jfs 2015-01-06 07:06:04

1

linux上令人讨厌的黑客攻击是使用timeout程序来运行该命令。但是,您可以选择更好的所有Python解决方案。

2

这是辅助函数使用:

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) 
+0

喜欢它:-)适合我们 - 非常感谢你! – 2013-04-15 21:05:25

+0

1.如果'command'生成大输出(足以填充其OS stdout/stderr管道缓冲区),则不会返回任何输出。您应该在等待超时时读取输出。 2.(小细节)如果'timeout'很大,那么循环会漂移,因为'time.sleep(0.1)'可以少睡/超过'0.1'秒。你可以使用'while endtime> timer():'来代替。 – jfs 2015-01-06 07:05:25

1

这里是使用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