signal模組簡介
最近在看Linux signal 相關內容,signal可以被用來進程間通訊和非同步處理。 Python標準函式庫提供了signal套件可以用來處理訊號相關。這裡討論的是Unix系統中Python的signal模組。
signal簡單範例
官方文件上有這樣的範例:
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內正常開啟文件,則清除定時器。
signal說明
基本的訊號名稱
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模組,但其可以使用給某一進程發送信號
範例1
# 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 的處理設為預設。
範例2
這個範例來自這裡。 需求是動態載入python導入的模組,也就是說,當導入的模組程式碼更新時,希望可以立即更新引用的程式碼。範例如下:
# 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() 方法。