超时使用模块“subprocess”
以下是运行任意命令返回stdout
数据的Python代码,或在非零退出代码上引发异常:
proc = subprocess.Popen(
cmd,
stderr=subprocess.STDOUT, # Merge stdout and stderr
stdout=subprocess.PIPE,
shell=True)
communicate
用于等待进程退出:
stdoutdata, stderrdata = proc.communicate()
subprocess
进程模块不支持超时 - 杀死运行超过X秒的进程的能力 - 因此, communicate
可能需要永远运行。
在Windows和Linux上运行的Python程序中实现超时的最简单方法是什么?
在Python 3.3+中:
from subprocess import STDOUT, check_output
output = check_output(cmd, stderr=STDOUT, timeout=seconds)
output
是包含命令的合并标准输出stderr数据的字节字符串。
与proc.communicate()
方法不同,此代码在问题文本中指定的非零退出状态引发CalledProcessError
。
我已经删除了shell=True
因为它经常被不必要地使用。 如果cmd
确实需要它,您可以随时添加它。 如果你添加shell=True
,如果子进程产生自己的后代; check_output()
返回的时间可能比timeout指示晚得多,请参阅子进程超时失败。
超时功能通过提供关于Python 2.x的subprocess32
的3.2+子模块的反向移植。
我对低层次的细节知之甚少; 但是,考虑到在Python 2.6中,API提供了等待线程和终止进程的能力,那么在独立线程中运行进程又该如何呢?
import subprocess, threading
class Command(object):
def __init__(self, cmd):
self.cmd = cmd
self.process = None
def run(self, timeout):
def target():
print 'Thread started'
self.process = subprocess.Popen(self.cmd, shell=True)
self.process.communicate()
print 'Thread finished'
thread = threading.Thread(target=target)
thread.start()
thread.join(timeout)
if thread.is_alive():
print 'Terminating process'
self.process.terminate()
thread.join()
print self.process.returncode
command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
command.run(timeout=3)
command.run(timeout=1)
这个片段在我的机器中的输出是:
Thread started
Process started
Process finished
Thread finished
0
Thread started
Process started
Terminating process
Thread finished
-15
可以看出,在第一次执行时,进程正确完成(返回码0),而在第二次执行中进程终止(返回码-15)。
我没有在Windows中测试; 但除了更新示例命令之外,我认为它应该起作用,因为我没有在文档中发现任何说thread.join或process.terminate不受支持的东西。
使用threading.Timer类可以简化jcollado的答案:
import shlex
from subprocess import Popen, PIPE
from threading import Timer
def run(cmd, timeout_sec):
proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE)
timer = Timer(timeout_sec, proc.kill)
try:
timer.start()
stdout, stderr = proc.communicate()
finally:
timer.cancel()
# Examples: both take 1 second
run("sleep 1", 5) # process ends normally at 1 second
run("sleep 5", 1) # timeout happens at 1 second
链接地址: http://www.djcxy.com/p/54685.html
上一篇: Using module 'subprocess' with timeout
下一篇: How to read all message from queue using stomp library in Python?