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

后端 未结 5 1947
暗喜
暗喜 2020-12-15 23:31

This has probably been asked but I cannot find anything regarding a subprocess.call timeout when using python 2.7

5条回答
  •  伪装坚强ぢ
    2020-12-16 00:15

    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. It works on Python 2.7 and it includes timeout support from Python 3.3.

    subprocess.call() is just Popen().wait() and therefore to interrupt a long running process in timeout seconds:

    #!/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:

    #!/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:

    #!/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.

提交回复
热议问题