Changeset 1533

Show
Ignore:
Timestamp:
04/23/08 11:10:07 (2 years ago)
Author:
JensDiemer
Message:

subprocess with timeout without threading

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • CodeSnippets/subprocess2.py

    r1526 r1533  
    66    ~~~~~~~~~~~~~~~~~~~~~~~ 
    77 
     8    http://www.python-forum.de/topic-14301.html 
     9    http://www.python-forum.de/post-23692.html#23692 
     10 
     11    Use some parts from the user 'droptix': 
     12        http://www.python-forum.de/post-96180.html#96180 
    813""" 
    914 
     
    1318 
    1419 
    15 import os, subprocess, threading, signal 
     20import os, sys, subprocess, signal, time 
    1621 
    17 KILL_SIGNAL = signal.SIGKILL 
     22if sys.platform == "win32": 
     23    import win32api 
     24    import win32con 
     25    import win32process 
     26    #FIRST_SIGNAL = win32con.CTRL_C_EVENT 
     27    FIRST_SIGNAL = win32con.CTRL_BREAK_EVENT 
     28else: 
     29    import signal 
     30    FIRST_SIGNAL = signal.SIGTERM # 15 
     31    SECOND_SIGNAL = signal.SIGKILL # 9 
    1832 
    19 class subprocess2(threading.Thread): 
     33DEFAULT_TIMEOUT = 5 
     34DEFAULT_WAIT_TIME = 0.25 
     35 
     36 
     37 
     38class Subprocess2(object): 
    2039    """ 
    21     subprocess with a timeout 
    22  
    23     Note: os.kill() doesn't exist under Windows! 
     40    subprocess with timeout 
    2441    """ 
    2542    def __init__(self, *args, **kwags): 
    26         self.killed = None 
     43        self.killed = False 
     44        self.kill_count = 0 
    2745 
    28         self.timeout = kwags.pop("timeout", 5) 
     46        self.timeout = kwags.pop("timeout", DEFAULT_TIMEOUT) 
     47        self.wait_time = kwags.pop("wait_time", DEFAULT_WAIT_TIME) 
     48        self.debug = kwags.pop("debug", False) 
    2949 
    30         self.args = args 
    31         self.kwags = kwags 
     50        self.start_time = time.time() 
     51        self.process = subprocess.Popen(*args, **kwags) 
     52        self.wait_loop() 
    3253 
    33         threading.Thread.__init__(self) 
     54    def wait_loop(self): 
     55        """ 
     56        Sleep and check if the subprocess is ended, if not terminate it. 
     57        """ 
     58        while True: 
     59            time.sleep(self.wait_time) 
     60            returncode = self.process.poll() 
     61            if self.debug: print "debug: returncode:", returncode 
     62            if returncode != None: 
     63                if self.debug: print "debug: process is terminated" 
     64                return 
     65            if time.time() - self.start_time >= self.timeout: 
     66                if self.debug: print "debug: timeout arrived" 
     67                self.killed = True 
     68                self.kill_count += 1 
     69                try: 
     70                    if sys.platform == "win32": 
     71                        self.win32_kill() 
     72                        return # We can only directly terminat the process 
     73                    else: 
     74                        self.os_kill() 
     75                finally: 
     76                    if self.kill_count >= 2: 
     77                        return 
    3478 
    35         self.start() 
    36         self.join(self.timeout) 
    37         self.stop() 
    3879 
    39     def run(self): 
     80    def win32_kill(self): 
    4081        """ 
    41         start child process and wait for terminate 
     82        terminate the subprocess under windows 
    4283        """ 
    43         self.process = subprocess.Popen(*self.args, **self.kwags) 
    44         self.process.wait() 
    45         if self.killed == None: 
    46             # The process terminate and was not killed in the past 
    47             self.killed = False 
     84        if self.debug: print "debug: terminal process" 
     85        h = win32api.OpenProcess( 
     86            win32con.PROCESS_ALL_ACCESS, False, 
     87            self.process.pid 
     88        ) 
     89        handle = h.handle 
     90        win32process.TerminateProcess(handle, 1) 
    4891 
    49     def stop(self): 
     92    def os_kill(self): 
    5093        """ 
    51         kill the child process if it's not terminated in the past 
     94        terminate the subporocess using os.kill() 
    5295        """ 
    53         if self.killed == False: 
    54             # process is terminate 
    55             return 
     96        if self.kill_count == 1: 
     97            if self.debug: print "debug: kill with FIRST_SIGNAL" 
     98            kill_signal = FIRST_SIGNAL 
    5699        else: 
    57             # kill a running process 
    58             self.killed = True 
    59             os.kill(self.process.pid, KILL_SIGNAL) 
     100            if self.debug: print "debug: kill with SECOND_SIGNAL" 
     101            kill_signal = SECOND_SIGNAL 
     102 
     103        os.kill(self.process.pid, kill_signal) 
     104 
    60105 
    61106 
    62107if __name__ == "__main__": 
    63108    print "try 'ls'..." 
    64     p = subprocess2("ls", 
     109    p = Subprocess2("ls", 
    65110        stdout=subprocess.PIPE, 
    66         shell=True, timeout = 1 
     111        shell=True, timeout = 1, debug = True 
    67112    ) 
    68113    print "returncode:", p.process.returncode 
     
    73118 
    74119    print "start the python interpreter..." 
    75     p = subprocess2("python", 
     120    p = Subprocess2("python", 
    76121        stdout=subprocess.PIPE, stderr=subprocess.PIPE, 
    77         shell=True, timeout = 1 
     122        shell=True, timeout = 1, debug = True 
    78123    ) 
    79124    print "returncode:", p.process.returncode