Python中並沒有Timeout模塊,但是在程序中經常遇到需要超時控制的情況。
有兩種思路去實現這種Timeout,其一是將需要做超時處理的代碼塊作爲一個獨立的子進程來處理,可將其另做一個包含main函數的.py文件。然後使用子進程超時限制來控制代碼塊運行的時間。
#!/usr/bin/python import signal import select import datetime import subprocess import os,sys,time '''input: command string split list''' def timeoutCmd(command, timeout): start = datetime.datetime.now() process = subprocess.Popen(command,stdout=subprocess.PIPE) while process.poll() is None: time.sleep(0.2) now = datetime.datetime.now() if (now - start).seconds > timeout: try: os.kill(process.pid, signal.SIGKILL) os.waitpid(-1, os.WNOHANG) except: pass return False return True
以上的方法可以實現將需要運行的命令作爲command參數 ,成爲當前進程的子進程,控制其運行時間。當子進程和主進程需要通信的時候,則可以使用文件通信。
'''input: command string''' def timeoutCommand(command, timeout): outMsg = [] pipeFile = "timeout_%s.txt" %time.mktime(time.localtime()) fileWriter = open(pipeFile, "w") cmd = command.split() start = datetime.datetime.now() process = subprocess.Popen(cmd, universal_newlines=True, stdout=fileWriter) while process.poll() is None: time.sleep(0.2) now = datetime.datetime.now() if (now - start).seconds > timeout: try: os.kill(process.pid, signal.SIGKILL) os.waitpid(-1, os.WNOHANG) except: pass break try: fileWriter.close() fileReaser = open(pipeFile, "r") outMsg = fileReaser.readlines() fileReaser.close() except: pass try: os.remove(pipeFile) except: pass return outMsg
Python程序超時的情況經常出現,將核心而且容易超時的代碼塊封裝成一個子進程來控制是一種十分穩妥的方法。