简体   繁体   English

如何使用python 2.7.6进行subprocess.call超时?

[英]How to make a subprocess.call timeout using python 2.7.6?

可能有人问过,但是在使用python 2.7时我找不到任何关于subprocess.call超时的信息

A simple way I've always done timeouts with 2.7 is utilizing subprocess.poll() alongside time.sleep() with a delay. 我总是使用2.7进行超时的一种简单方法是使用subprocess.poll()time.sleep()以及延迟。 Here's a very basic example: 这是一个非常基本的例子:

import subprocess
import time

x = #some amount of seconds
delay = 1.0
timeout = int(x / delay)

args = #a string or array of arguments
task = subprocess.Popen(args)

#while the process is still executing and we haven't timed-out yet
while task.poll() is None and timeout > 0:
     #do other things too if necessary e.g. print, check resources, etc.
     time.sleep(delay)
     timeout -= delay

If you set x = 600 , then your timeout would amount to 10 minutes. 如果设置x = 600 ,则超时将达到10分钟。 While task.poll() will query whether or not the process has terminated. task.poll()将查询进程是否已终止。 time.sleep(delay) will sleep for 1 second in this case, and then decrement the timeout by 1 second. 在这种情况下, time.sleep(delay)将休眠1秒,然后将超时减少1秒。 You can play around with that part to your heart's content, but the basic concept is the same throughout. 你可以根据自己的内容来玩这个部分,但基本概念始终如一。

Hope this helps! 希望这可以帮助!

subprocess.poll() https://docs.python.org/2/library/subprocess.html#popen-objects subprocess.poll() https://docs.python.org/2/library/subprocess.html#popen-objects

You could install subprocess32 module mentioned by @gps -- the backport of the subprocess module from Python 3.2/3.3 for use on 2.x. 你可以安装subprocess32模块 由@gps提到的的反向移植- subprocess在Python 3.2 / 3.3模块上使用2.x的 It works on Python 2.7 and it includes timeout support from Python 3.3. 它适用于Python 2.7,它包括Python 3.3的超时支持。

subprocess.call() is just Popen().wait() and therefore to interrupt a long running process in timeout seconds: subprocess.call()只是Popen().wait() ,因此在timeout秒内中断一个长时间运行的进程:

#!/usr/bin/env python
import time
from subprocess import Popen

p = Popen(*call_args)
time.sleep(timeout)
try:
    p.kill()
except OSError:
    pass # ignore
p.wait()

If the child process may end sooner then a portable solution is to use Timer() as suggested in @sussudio's answer : 如果子进程可能会更快结束,那么便携式解决方案是使用@ sussudio的答案中建议的Timer()

#!/usr/bin/env python
from subprocess import Popen
from threading import Timer

def kill(p):
    try:
        p.kill()
    except OSError:
        pass # ignore

p = Popen(*call_args)
t = Timer(timeout, kill, [p])
t.start()
p.wait()
t.cancel()

On Unix, you could use SIGALRM as suggested in @Alex Martelli's answer : 在Unix上,您可以按照@Alex Martelli的回答中的建议使用SIGALRM

#!/usr/bin/env python
import signal
from subprocess import Popen

class Alarm(Exception):
    pass

def alarm_handler(signum, frame):
    raise Alarm

signal.signal(signal.SIGALRM, alarm_handler)


p = Popen(*call_args)
signal.alarm(timeout)  # raise Alarm in 5 minutes
try:
    p.wait()
    signal.alarm(0)  # reset the alarm
except Alarm:
    p.kill()
    p.wait()

To avoid using threads and signals here, subprocess module on Python 3 uses a busy loop with waitpid(WNOHANG) calls on Unix and winapi.WaitForSingleObject() on Windows . 为了避免在这里使用线程和信号,Python 3上的subprocess模块使用一个繁忙的循环,在Unix上使用waitpid(WNOHANG)调用, 在Windows 上使用 winapi.WaitForSingleObject()

You can try to use "easyprocess" : 您可以尝试使用“easyprocess”

https://github.com/ponty/EasyProcess https://github.com/ponty/EasyProcess

It has many features that you need like "timeout" . 它有许多你需要的功能,如“超时”

You can use subprocess32 mentioned by @gps , which is backport of the subprocess standard library module from Python 3.2 - 3.5 for use on Python 2. 您可以使用subprocess32 通过@gps提到的 ,这是在Python 3.2的子标准库模块的反向移植- 3.5上使用的Python 2。

Firstly, install the subprocess32 module: 首先,安装subprocess32模块:

pip install subprocess32

Here's a code snippet: 这是一段代码片段:

>>> import subprocess32
>>> print subprocess32.check_output(["python", "--version"])
Python 2.7.12

>>> subprocess32.check_output(["sleep", "infinity"], timeout=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/subprocess32.py", line 340, in check_output
    raise TimeoutExpired(process.args, timeout, output=output)
subprocess32.TimeoutExpired: Command '['sleep', 'infinity']' timed out after 3 seconds

Notice, default timeout=None , which means never timeout. 注意,默认timeout=None ,这意味着永不超时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM