Python——signal


  該模塊為在Python中使用信號處理句柄提供支持。下面是一些使用信號和他們的句柄時需要注意的事項:

  • 除了信號 SIGCHLD 的句柄遵從底層的實現外,專門針對一個信號的句柄一旦設置,除非被明確地重置,會保持被設置的狀態。(Python 模擬 BSD 風格的界面,而不論底層的實現)。 
  • 不能從 critical sections 設法臨時阻止信號,因為Unix的風格並不支持這么做。
  • 盡管從 Python 用戶的角度,Python 的信號句柄被稱為異步的,但他們也只能出現在 Python 解釋器的“原子”指令之間。如果在以純 C 書寫的長運算正在進行中有信號到達,那么這個信號可能被延遲任意長的時間。
  • 當信號在 I/O 操作過程中到來時, I/O 操作可能會在信號句柄返回后拋出異常。這依賴於底層 Unix 關於被打斷的系統調用的語義。
  • 因為 C 的信號句柄總有返回值,捕獲同步的錯誤比如 SIGFPE 或 SIGSEGV 的意義不大。
  • Python 會默認設置一些信號句柄: SIGPIPE 被忽略 (因此管道和套接字上的寫錯誤可以像普通的 Python 異常一樣報告) , SIGINT 被轉成一個 KeyboardInterrupt 異常。不過這些都是可以覆寫的。
  • 同一段程序中如果既有線程又有信號,那么就要小心了:總是在執行的主線程中執行 signal() 操作。任何一個 thread 都可以執行 alarm()getsignal()pause(),setitimer() 或 getitimer(); 只有 main thread 才能設置一個新的信號句柄,而且只有 main thread 才能夠接收信號 (Python 的 signal 模塊就是這么規定的,不論底層的線程實現是否允許向獨立的線程發送信號)。這意味着信號不能被用來充當線程間的通信手段,在Python中請使用鎖。

 

  目錄

  一、signal 模塊中的變量

    1. signal.SIG_DFL

    2. signal.SIG_IGN

    3. SIG*

    4. signal.CTRL_C_EVENT

    5. signal.CTRL_BREAK_EVENT

    6. signal.NSIG

    7. signal.ITIMER_REAL

    8. signal.ITIMER_VIRTUAL

    9. signal.ITIMER_PROF

 

  二、signal 模塊中的異常

    signal.ItimerError

 

  三、signal 模塊中的函數

    1. signal.alarm()

    2. signal.getsignal()

    3. signal.pause()

    4. signal.settimer()

    5. signal.gettimer()

    6. signal.get_wakeup_fd()

    7. signal.siginterrupt()

    8. signal.signal()

 

一、signal 模塊中的變量:

  

 signal.SIG_DFL 

  
  這是兩個標准信號句柄選項之一,將會執行為信號設置的默認函數。例如,在大多數的系統上對於 SIGQUIT 的默認動作是 dump 內核然后退出,而對於 SIGCHLD 的默認動作是直接無視它。
  
  signal.SIG_IGN 
  
  這是兩個標准信號句柄選項這種的另一個,直接忽略指定的信號。
  
 SIG* 
  
  所有的信號數都以符號常量的形式定義,例如,掛起信號被定義為  signal.SIGHUP,變量名與 C 程序中使用的相同,可以在 <signal.h> 頭文件中找到。Unix 對應 ‘signal()‘ 的 man 頁面列出了所有已經定義的信號,(有些系統上是 signal(2),有的系統上是 signal(7))。注意不是所有的系統上都定義相同的信號名。
  
  signal.CTRL_C_EVENT 
  
  對應於  CTRL+C 擊鍵事件,該信號只能與 os.kill() 一起使用。
  適用於: Windows.
   Python 2.7 引入
  
 signal.CTRL_BREAK_EVENT 
  
   對應 CTRL+BREAK 擊鍵操作,該信號只能與 os.kill() 一起使用。
  適用於: Windows.
   Python 2.7 引入
  
 signal.NSIG 
  
  剛好比最大信號的值大1。
  
 signal.ITIMER_REAL 
  
  實時遞減定時器,過期時發出  SIGALRM 信號
  
  signal.ITIMER_VIRTUAL 
  
  只有當進程正在執行時才遞減定時器,過期時發出 SIGVTALRM 信號
  
  signal.ITIMER_PROF 
  
  當進程正在執行或系統正在代進程執行時遞減定時器,過期時發出 SIGPROF 信號,當與 ITIMER_VIRTUAL 一起使用時,這個定時器通常用來刻畫應用在用戶空間和內核中所花的時間。
  

二、signal 模塊的異常
  
  signal.ItimerError  
  
  從底層  setitimer() 或 getitimer() 拋出,用來標志一個錯誤。該異常在 一個無效的計時器或負的時間被傳入 setitimer() 時拋出,是 IOError 的子類。
  

三、signal 模塊的函數

  

 signal.alarm(time) 

  

  如果參數 time 是非零的,這個函數會請求一個 SIGALRM 信號在 time 秒內發給進程。先前已經調度的 alarm 全部取消 (一次只能調度一個 alarm )。 返回值是先前設置的 alarm 還剩余的秒數。如果 time 是零,不會調度任何 alarm ,而且會取消一切已經調度的 alarm 。如果返回值是零,說明當前沒有被調度的 alarm 。(查看 Unix man 手冊 alarm(2).)

  適用於: Unix

  

 signal.getsignal(signalnum) 

  

  返回值是對應於信號 signalnum 的信號句柄,可能是一個Python 可調用對象,或者是 signal.SIG_IGNsignal.SIG_DFL 或 None 中的一個。這里 signal.SIG_IGN 意味着該信號此前被忽略, signal.SIG_DFL 意味着先前使用默認方式處理這個信號, None 意味着先前的信號句柄沒有設置。

  

 signal.pause() 

  

  造成進程睡眠直到信號到來,合適的句柄到時會被調用,沒有返回值,不支持Windows。(查看 Unix man 手冊 signal(2))。

  

 signal.setitimer(which, seconds[, interval]) 

  

  將參數 which 指定的計時器 ( signal.ITIMER_REALsignal.ITIMER_VIRTUAL 或 signal.ITIMER_PROF 中的一個) 設置為參數 seconds 秒后觸發(float 型的也可,不同於 alarm()) ,然后每隔 interval 秒后觸發一次。通過將 seconds 設置為0可以清除 which 指定的計時器。

  當一個計時器觸犯時,一個信號被發送給進程,這個被發送的信號取決於使用的定時器, signal.ITIMER_REAL 會發送 SIGALRM , signal.ITIMER_VIRTUAL 發送 SIGVTALRM, signal.ITIMER_PROF 發送 SIGPROF。

  舊值被作為元組返回:(delay, interval)。

  傳入一個無效的定時器會造成一個 ItimerError 

  適用於: Unix.

  Python 2.6 引入

  

 signal.getitimer(which) 

 

  返回參數 which 指定的定時器的當前值

  適用於: Unix.

  Python 2.6 引入

  

 signal.set_wakeup_fd(fd) 

     

  將喚醒文件描述字設置為參數 fd。當一個信號被接收時,一個 '\0' 字節被寫入到指定的 fd 中。 可以被一個一個庫用來喚醒一個 poll 或 select 調用,允許信號被完全處理。

  返回舊的文件描述字,參數 fd 必須是非阻塞的,是否在再次調用 poll 或 select 之前清除字節記錄取決於具體的庫。

  當允許線程時,該函數只能被主線程調用,其他的線程調用它將會拋出 ValueError 異常。

  Python 2.6 引入

  

 signal.siginterrupt(signalnum, flag) 

 

  改變系統調用重啟規則:如果 flag 是 False 系統調用將會在被信號 signalnum 打斷時重啟,否則系統調用將會被打斷。沒有返回值。

   適用於: Unix (查看 man 手冊的 siginterrupt(3))

  注意當用 signal() 設置一個信號句柄時將會通過隱式調用 siginterrupt()  重置重啟行為為可打斷,即對於指定的的信號,flag 為 真。

  Python 2.6 引入

 

 signal.signal(signalnum, handler)

  

  將信號 signalnum 的句柄設置為函數 handler。 handler 可以是一個 Python 可調用對象,接受兩個參數,或 signal.SIG_IGN 和 signal.SIG_DFL 中的一個。該函數將會返回之前的信號句柄,

  當允許線程時,該函數只能被主線程調用,其他的線程調用它將會拋出 ValueError 異常。

  調用句柄 handler 需要提供兩個參數:信號的數值和當前的棧幀 (None 或一個 frame 對象;查閱 description in the type hierarchy 或 inspect 模塊中的屬性描述可以了解 frame 對象)。

  Windows上 signal() 只能用 SIGABRT,SIGFPE,SIGILL,SIGINT,SIGSEGV 或 SIGTERM 調用。 否則會拋出 ValueError 異常。

 

例子

  這里有一個例子,使用 alarm() 函數來限制等待打開一個文件的時間,當文件是為一個不一定會被打開的連續設備准備時很有用,這種情況通常會造成 os.open() 立刻掛起。解決辦法是在開文件錢設置一個5秒的 alarm,當打開文件超時時,  alarm 信號會被發送,句柄將會拋出一個異常。

  

import signal, os

def handler(signum, frame):
    print 'Signal handler called with signal', signum
    raise IOError("Couldn't open device!")

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)

signal.alarm(0)          # Disable the alarm

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM