Changeset 1533
- Timestamp:
- 04/23/08 11:10:07 (2 years ago)
- Files:
-
- 1 modified
-
CodeSnippets/subprocess2.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
CodeSnippets/subprocess2.py
r1526 r1533 6 6 ~~~~~~~~~~~~~~~~~~~~~~~ 7 7 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 8 13 """ 9 14 … … 13 18 14 19 15 import os, s ubprocess, threading, signal20 import os, sys, subprocess, signal, time 16 21 17 KILL_SIGNAL = signal.SIGKILL 22 if 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 28 else: 29 import signal 30 FIRST_SIGNAL = signal.SIGTERM # 15 31 SECOND_SIGNAL = signal.SIGKILL # 9 18 32 19 class subprocess2(threading.Thread): 33 DEFAULT_TIMEOUT = 5 34 DEFAULT_WAIT_TIME = 0.25 35 36 37 38 class Subprocess2(object): 20 39 """ 21 subprocess with a timeout 22 23 Note: os.kill() doesn't exist under Windows! 40 subprocess with timeout 24 41 """ 25 42 def __init__(self, *args, **kwags): 26 self.killed = None 43 self.killed = False 44 self.kill_count = 0 27 45 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) 29 49 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() 32 53 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 34 78 35 self.start()36 self.join(self.timeout)37 self.stop()38 79 39 def run(self):80 def win32_kill(self): 40 81 """ 41 start child process and wait for terminate82 terminate the subprocess under windows 42 83 """ 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) 48 91 49 def stop(self):92 def os_kill(self): 50 93 """ 51 kill the child process if it's not terminated in the past94 terminate the subporocess using os.kill() 52 95 """ 53 if self.kill ed == False:54 # process is terminate55 return96 if self.kill_count == 1: 97 if self.debug: print "debug: kill with FIRST_SIGNAL" 98 kill_signal = FIRST_SIGNAL 56 99 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 60 105 61 106 62 107 if __name__ == "__main__": 63 108 print "try 'ls'..." 64 p = subprocess2("ls",109 p = Subprocess2("ls", 65 110 stdout=subprocess.PIPE, 66 shell=True, timeout = 1 111 shell=True, timeout = 1, debug = True 67 112 ) 68 113 print "returncode:", p.process.returncode … … 73 118 74 119 print "start the python interpreter..." 75 p = subprocess2("python",120 p = Subprocess2("python", 76 121 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 77 shell=True, timeout = 1 122 shell=True, timeout = 1, debug = True 78 123 ) 79 124 print "returncode:", p.process.returncode