在python中,如何在subprocess*中使用timeout并*获取outpu

2024-06-01 06:42:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我用了这两个问题的密码

how to get the return value from a thread in python

subprocess with timeout

得到了这个

import subprocess, threading, os

class ThreadWithReturnValue(threading.Thread):
    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, Verbose=None):
        threading.Thread.__init__(self, group, target, name, args, kwargs, Verbose)
        self._return = None

    def run(self):
        if self._Thread__target is not None:
            self._return = self._Thread__target(*self._Thread__args, **self._Thread__kwargs)

    def join(self, timeout = None):
        threading.Thread.join(self, timeout)
        return self._return

class SubprocessWrapper(object):
    def __init__(self, cmd, timeout):
        self.cmd = cmd
        self.process = None
        self.timeout = timeout
    def run(self):
        def target(cmd):
            self.process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr = subprocess.PIPE)
            returnValue = self.process.communicate()
            return [returnValue[0], returnValue[1], self.process.returncode]

        thread = ThreadWithReturnValue(target=target, args=[self.cmd])
        thread.start()
        returnValue = thread.join(self.timeout)
        if thread.is_alive():
            print 'cmd = ',self.cmd
            self.process.kill()
            returnValue = thread.join()
            print 'rc = ', returnValue[2]
        output = returnValue[0]
        error = returnValue[1]
        rc = returnValue[2]
        return (output, rc)

os.system('date +%T.%N')
s1 = SubprocessWrapper("echo 'Process started'; sleep 2; echo 'Process finished'", timeout = 3)
s1.run()
os.system('date +%T.%N')
s2 = SubprocessWrapper("echo 'Process started'; sleep 2; echo 'Process finished'", timeout = 1)
s2.run()
os.system('date +%T.%N')

问题是输出是

^{pr2}$

所以你可以看到,原本应该在一秒钟后终止的进程实际上花了2秒。这是因为join()的缘故,但在问题subprocess with timeout中,这很好。这意味着,当我整合了这两个代码时,我的问题是如何解决它?我在想我可能需要以不同的方式调用threading.Thread.__init__方法,但我不明白如何调用。在


Tags: selfcmdnonetargetreturnosdeftimeout
1条回答
网友
1楼 · 发布于 2024-06-01 06:42:35

尽管超时,此代码不会在一秒钟内返回输出。它在睡眠后两秒钟内返回:

#!/usr/bin/env python3
from subprocess import TimeoutExpired, check_output as qx
from timeit import default_timer as timer

start = timer()
try:
    qx("echo 'Process started'; sleep 2; echo 'Process finished'",
       shell=True, universal_newlines=True, timeout=1)
except TimeoutExpired as e:
    print("Got %r in %.2f seconds" % (e.output, timer() - start))
else:
    assert 0 # should not get here

输出

^{pr2}$

来自"Stop reading process output in Python without hang?" question的基于报警的解决方案:

#!/usr/bin/env python
import signal
from subprocess import Popen, PIPE
from timeit import default_timer as timer

class Alarm(Exception):
    pass

def alarm_handler(signum, frame):
    raise Alarm

start = timer()
# start process
process = Popen("echo 'Process started'; sleep 2; echo 'Process finished'",
                shell=True, stdout=PIPE, bufsize=1, universal_newlines=True)

# set signal handler
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(1) # produce SIGALRM in a second
buf = []
try:
    for line in iter(process.stdout.readline, ""):
        buf.append(line) # assume it is atomic
except Alarm:
    process.kill()
else:
    signal.alarm(0) # reset alarm
finally:
    output = ''.join(buf)
print("Got %r in %.2f seconds" % (output, timer() - start))
process.stdout.close()
process.wait()

输出

Got 'Process started\n' in 1.00 seconds

相关问题 更多 >