最近在看Linux signal
相關內容,signal能夠被用來進程間通訊和異步處理。Python標準庫提供了signal包能夠用來處理信號相關。這裏討論的是Unix系統中Python的signal模塊。html
官方文檔上有這樣的示例:python
import signal, os # 定義一個信號處理函數,該函數打印收到的信號,而後raise IOError def handler(signum, frame): print 'Signal handler called with signal', signum raise IOError("Couldn't open device!") # 對SIGALRM(終止)設置處理的handler, 而後設置定時器,5秒後觸發SIGALRM信號 signal.signal(signal.SIGALRM, handler) signal.alarm(5) # This open() may hang indefinitely fd = os.open('/dev/ttyS0', os.O_RDWR) signal.alarm(0) # 關閉定時器
該示例實現的功能是,爲了防止打開一個文件出錯或者其餘異常一直處於等待的狀態,設定一個定時器,5秒後觸發IOError。若是5s內正常打開文件,則清除定時器。api
import signal signal.SIGABORT signal.SIGHUP # 鏈接掛斷 signal.SIGILL # 非法指令 signal.SIGINT # 鏈接中斷 signal.SIGKILL # 終止進程(此信號不能被捕獲或忽略) signal.SIGQUIT # 終端退出 signal.SIGTERM # 終止 signal.SIGALRM # 超時警告 signal.SIGCONT # 繼續執行暫停進程 等等...
signal.signal(signalnum, handler)異步
設置信號處理的函數
signal.alarm(time)函數
設置發送SIGALRM信號的定時器
os.killrest
這個不屬於signal模塊,但其能夠使用給某一進程發送信號
# From project httpscreenshot-master, under directory , in source file httpscreenshot.py. def timeoutFn(func, args=(), kwargs={}, timeout_duration=1, default=None): import signal class TimeoutError(Exception): pass def handler(signum, frame): raise TimeoutError() # set the timeout handler signal.signal(signal.SIGALRM, handler) signal.alarm(timeout_duration) try: result = func(*args, **kwargs) except TimeoutError as exc: result = default finally: signal.alarm(0) signal.signal(signal.SIGALRM, signal.SIG_DFL) return result
上面這個示例實現了設置函數執行超時返回默認結果的功能。先是設置了一個超時處理函數,在函數中拋出自定義的拋出異常。在執行函數前設置了 signal.alarm
,當超出時間後觸發拋出異常 SIGALRM
, 而後捕獲這個異常設置默認值,最後作下清理工做將定時器取消,而且將對 SIGALRM
的處理設爲默認。code
這個示例來源於這裏。 需求是動態加載python導入的模塊,也就是說,當導入的模塊代碼更新時,但願能夠當即更新引用的代碼。示例以下:htm
# lib.py def scrape_me_bro(): print "Scraping is fun" #scrape.py import time import signal import lib def scrape(): # Assume we are hitting Streaming API # and doing something buzzwordy with it while True: lib.scrape_me_bro() time.sleep(2) def reload_libs(signum, frame): print "Received Signal: %s at frame: %s" % (signum, frame) print "Excuting a Lib Reload" reload(lib) # Register reload_libs to be called on restart signal.signal(signal.SIGHUP, reload_libs) # Main scrape()
當運行scrape.py時,程序會每一個兩秒調用一次lib.py中的 scrape_me_bro()
方法,這時候若是lib.py裏的方法變化了,向運行scrape.py的進程發送 SIGHUP
信號,那麼它會從新加載lib.py,這樣會接着循環執行修改後的 scrape_me_bro()
方法。blog
《Beginning Linux Programming》進程