windows - Run subprocess in python and get stdout and kill process on timeout -


here code, launches subprocess, waits till ends , returns stdout, or timeout happens , raises exception. common use print(run('python --version').execute())

class run(object):     def __init__(self, cmd, timeout=2*60*60):         self.cmd = cmd.split()         self.timeout = timeout         self._stdout = b''         self.dt = 10         self.p = none      def execute(self):         print("execute command: {}".format(' '.join(self.cmd)))          def target():             self.p = popen(self.cmd, stdout=pipe, stderr=stdout)             self._stdout = self.p.communicate()[0]          thread = thread(target=target)         thread.start()          t = 0         while t < self.timeout:             thread.join(self.dt)             if thread.is_alive():                 t += self.dt                 print("running for: {} seconds".format(t))             else:                 ret_code = self.p.poll()                 if ret_code:                     raise assertionerror("{} failed.\nretcode={}\nstdout:\n{}".format(                         self.cmd, ret_code, self._stdout))                 return self._stdout          else:             print('timeout {} reached, kill task, pid={}'.format(self.timeout, self.p.pid))             self.p.terminate()             thread.join()             raise assertionerror("timeout") 

the problem following case. process launch spawns more child processes. when timeout reached, kill main process (the 1 srarted using class) self.p.terminate(), children remaining , code hangs on line self._stdout = self.p.communicate()[0]. , execution continues if manually kill child processes.

i tried soulution when instead of self.p.terminate() kill whole process tree.

this not work if main process finished , children existing on own, , have no ability find , kill them. blocking self.p.communicate().

is there way solve this?

you use processwrapper pysys framework - offers alot of functionality abstraction in cross platform way i.e.

import sys, os pysys.constants import * pysys.process.helper import processwrapper pysys.exceptions import processtimeout  command=sys.executable arguments=['--version'] try:     process = processwrapper(command, arguments=arguments, environs=os.environ, workingdir=os.getcwd(), stdout='stdout.log', stderr='stderr.log', state=foreground, timeout=5.0)     process.start() except processtimeout:     print "process timeout"     process.stop() 

it's @ sourceforge (http://sourceforge.net/projects/pysys/files/ , http://pysys.sourceforge.net/) if of interest.


Comments