首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在超时的情况下使用模块“子进程”

在超时的情况下使用模块“子进程”
EN

Stack Overflow用户
提问于 2009-07-28 00:41:23
回答 31查看 375K关注 0票数 369

下面是运行返回其stdout数据的任意命令的Python代码,或者对非零退出代码引发异常:

代码语言:javascript
复制
proc = subprocess.Popen(
    cmd,
    stderr=subprocess.STDOUT,  # Merge stdout and stderr
    stdout=subprocess.PIPE,
    shell=True)

communicate用于等待进程退出:

代码语言:javascript
复制
stdoutdata, stderrdata = proc.communicate()

subprocess模块不支持超时--停止运行超过X秒的进程的能力--因此,communicate可能要花费很长时间才能运行。

程序中实现超时的最简单的方法是什么?

EN

回答 31

Stack Overflow用户

回答已采纳

发布于 2012-10-02 21:06:25

在Python 3.3+中:

代码语言:javascript
复制
from subprocess import STDOUT, check_output

output = check_output(cmd, stderr=STDOUT, timeout=seconds)

output是一个字节字符串,包含命令的合并的stdout、stderr数据。

check_output在问题的文本中指定的非零退出状态下引发CalledProcessError,这与proc.communicate()方法不同。

我删除了shell=True,因为它经常被不必要地使用。如果cmd确实需要它,则始终可以将其添加回。如果添加shell=True,即,如果子进程产生自己的后代;check_output()返回的时间可能比超时所指示的要晚得多,请参见子进程超时故障

在Python2.x上可以通过subprocess32子进程模块的3.2+后端端口获得超时特性。

票数 220
EN

Stack Overflow用户

发布于 2011-01-28 07:39:08

我不太了解底层的细节;但是,考虑到在python2.6中API提供了等待线程和终止进程的能力,那么在单独的线程中运行进程会怎么样呢?

代码语言:javascript
复制
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)

在我的机器中,这个片段的输出是:

代码语言:javascript
复制
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的内容。

票数 215
EN

Stack Overflow用户

发布于 2012-04-04 13:36:49

jcollado的答案可以使用threading.Timer类进行简化:

代码语言:javascript
复制
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
票数 158
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1191374

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档