歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Python 信號處理 signal 模塊

Table of Contents

  • 1. signal模塊簡介
    • 1.1. signal簡單示例
    • 1.2. signal說明
      • 1.2.1. 基本的信號名
      • 1.2.2. 常用信號處理函數
  • 2. signal使用示例
    • 2.1. 示例1
    • 2.2. 示例2
  • 3. 參考資料

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.alarm(time)
    設置發送SIGALRM信號的定時器
  • os.kill
    這個不屬於signal模塊,但其可以使用給某一進程發送信號

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() 方法。

參考資料

  • 《Beginning Linux Programming》
  • https://docs.python.org/2/library/signal.html
  • http://engineerwithoutacause.com/easy-signal-handling-for-python-daemons.html
  • http://www.programcreek.com/python/example/1220/signal.SIGALRM

Copyright © Linux教程網 All Rights Reserved