Вот то, что я использую, примерно:
from datetime import datetime
from time import time
import subprocess
import sys
import threading
import os
class Execution(threading.Thread):
comm = None
proc = None
returncode = None
stdoutdata = None
stderrdate = None
def __init__(self, comm):
threading.Thread.__init__(self)
self.comm = comm
def run(self):
self.proc = subprocess.Popen(self.comm, bufsize=-1, stdin=None,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.proc.wait()
(self.stdoutdata, self.stderrdata) = self.proc.communicate()
self.returncode = self.proc.poll()
for curcommand in somecommandlist:
ex = Execution(curcommand)
starttime = time()
ex.start()
ex.join(some_timeout_in_seconds)
wastimeout = False
if (ex.isAlive()):
wastimeout = True
print("TIMEOUT OCCURRED @ %s" % (datetime.today(),))
ex.proc.kill()
ex.join()
endtime = time()
duration = endtime - starttime
print("DURATION %s" % (duration,))
exitcode = ex.returncode
print("EXIT CODE: %s" % (exitcode,))
print somepostprocessing(ex.stdoutdata,ex.stderrdata)
sys.stdout.flush()
По сути: запустить процесс в отдельном потоке.Это необходимо, потому что модуль threading
дает вам время ожидания, а модуль subprocess
- нет.Подождите до истечения времени ожидания;проверьте, жива ли нить.Если поток работает, мы прекращаем его, убивая процесс (здесь subprocess
дает вам конструкцию kill()
, а threading
- нет) и ожидая завершения потока самостоятельно.
Имейте в виду, что communicate()
блокирует и сохраняет вывод full дочерних stderr и stdout, поэтому это может не сработать, если вывод очень большой.