0

これら2つの質問でコードを使用しました

Pythonでスレッドから戻り値を取得する方法

タイムアウトのあるサブプロセス

そしてこれを手に入れた

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')

問題は、出力が

11:20:34.963947950
11:20:36.986685289
cmd =  echo 'Process started'; sleep 2; echo 'Process finished'
rc =  -9
11:20:38.995597397

つまり、1 秒後に終了するはずだったプロセスが、実際には 2 秒かかったことがわかります。これはが原因で発生しますjoin()が、問題ではsubprocess with timeoutこれは正常に機能します。これは、両方のコードを統合したときにこの問題が発生したことを意味します。私の質問は、それを修正する方法ですか? 別の方法でメソッドを呼び出す必要があるのではないかと考えていthreading.Thread.__init__ましたが、方法がわかりません。

4

1 に答える 1