下面是运行任意命令返回其标准输出数据的Python代码,或在非零退出码上引发异常:
proc = subprocess.Popen(
cmd,
stderr=subprocess.STDOUT, # Merge stdout and stderr
stdout=subprocess.PIPE,
shell=True)
communication用于等待进程退出:
stdoutdata, stderrdata = proc.communicate()
子进程模块不支持超时——杀死运行超过X秒的进程的能力——因此,通信可能需要很长时间才能运行。
在Windows和Linux上运行的Python程序中实现超时的最简单方法是什么?
我已经修改了sussudio的答案。现在函数返回:(returncode, stdout, stderr, timeout) - stdout和stderr被解码为utf-8字符串
def kill_proc(proc, timeout):
timeout["value"] = True
proc.kill()
def run(cmd, timeout_sec):
proc = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
timeout = {"value": False}
timer = Timer(timeout_sec, kill_proc, [proc, timeout])
timer.start()
stdout, stderr = proc.communicate()
timer.cancel()
return proc.returncode, stdout.decode("utf-8"), stderr.decode("utf-8"), timeout["value"]
我对底层细节了解不多;但是,考虑到这一点
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中测试;但是,除了更新示例之外
命令,我想它应该工作,因为我还没有找到
记录任何说明该线程的内容。Join或process.terminate
不支持。
从Python 3.5开始,有了一个新的subprocess.run通用命令(意味着取代check_call, check_output…),它也有timeout=参数。
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)
执行args描述的命令。等待命令完成,然后返回一个CompletedProcess实例。
它引发一个子流程。超时超时时出现TimeoutExpired异常。