python signal信號


  作用:發送和接收異步系統信號

  信號是一個操作系統特性,它提供了一個途徑可以通知程序發生了一個事件並異步處理這個事件。信號可以由系統本身生成,也可以從一個進程發送到另一個進程。

由於信號會中斷程序的正常控制流,如果在中間接收到信號,有些操作(特別是I/O操作)可能會發生錯誤。

 

接收信號:

  signal.signal(sig,action)

  sig為某個信號,action為該信號的處理函數

  例如:

    signal.signal(signal.SIGALRM, hanlder)       hanlder為信號處理函數

  windows下sig信號:

  >>> dir(signal)
  ['CTRL_BREAK_EVENT', 'CTRL_C_EVENT', 'NSIG', 'SIGABRT', 'SIGBREAK', 'SIGFPE',
  'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_IGN', '__doc__', '__name__', '__package__',
  'default_int_handler', 'getsignal', 'set_wakeup_fd', 'signal']

  linux下sig信號:

   

  >>> dir(signal)
  ['ITIMER_PROF', 'ITIMER_REAL', 'ITIMER_VIRTUAL', 'ItimerError', 'NSIG', 'SIGABRT', 'SIGALRM', 'SIGBUS', 'SIGCHLD', 
  'SIGCLD', 'SIGCONT', 'SIGFPE', 'SIGHUP', 'SIGILL', 'SIGINT', 'SIGIO', 'SIGIOT', 'SIGKILL', 'SIGPIPE', 'SIGPOLL',
  'SIGPROF', 'SIGPWR', 'SIGQUIT', 'SIGRTMAX', 'SIGRTMIN', 'SIGSEGV', 'SIGSTOP', 'SIGSYS', 'SIGTERM', 'SIGTRAP',
  'SIGTSTP', 'SIGTTIN', 'SIGTTOU', 'SIGURG', 'SIGUSR1', 'SIGUSR2', 'SIGVTALRM', 'SIGWINCH', 'SIGXCPU', 'SIGXFSZ',
  'SIG_DFL', 'SIG_IGN', '__doc__', '__name__', '__package__', 'alarm', 'default_int_handler', 'getitimer', 'getsignal',
  'pause', 'set_wakeup_fd', 'setitimer', 'siginterrupt', 'signal']   >>>

 

  即通過建立一個回調函數來接收信號,這個回調函數稱為信號處理函數(signal hanlder),它會在信號出現時調用。

 信號處理函數包括信號編號及被信號中斷那一時刻的棧幀。

  

  def hanlder(signum, frame):

      something...

 

  signum即信號編號( 數字),例如:

  

  Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32
  Type "copyright", "credits" or "license()" for more information.
  >>> import signal
  >>> signal.SIGINT
  2
  >>> 

  frame為被信號中斷那一時刻的棧幀。

==================================================================

接收信號:signal.signal(sig,action)

官方文檔:
signal. signal (signalnum, handler)

Set the handler for signal signalnum to the function handler. handler can be a callable Python object taking two arguments (see below), or one of the special values signal.SIG_IGN or signal.SIG_DFL. The previous signal handler will be returned (see the description of getsignal() above). (See the Unix man page signal(2).)

When threads are enabled, this function can only be called from the main thread; attempting to call it from other threads will cause a ValueError exception to be raised.

The handler is called with two arguments: the signal number and the current stack frame (None or a frame object; for a description of frame objects, see the description in the type hierarchy or see the attribute descriptions in the inspect module).

On Windows, signal() can only be called with SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM. A ValueError will be raised in any other case.

import signal
import os
import time

def receive_signal(signum, stack):
    print 'Received:', signum

# 注冊信號處理程序
signal.signal(signal.SIGUSR1, receive_signal)
signal.signal(signal.SIGUSR2, receive_signal)

# 打印這個進程的PID方便使用kill傳遞信號
print 'My PID is:', os.getpid()

# 等待信號,有信號發生時則調用信號處理程序
while True: print 'Waiting...' time.sleep(3)

SIGUSR1和SIGUSR2是留給用戶使用的信號。windows下無這兩個信號。

這個腳本會無限循環,每次暫停3秒鍾。有信號到來時,sleep()調用被中斷,信號處理程序receive_signal被調用.信號處理程序返回時,循環繼續。

==================================================================

發送信號:os.kill(pid, sig)

>>> import os
>>> help(os.kill)
Help on built-in function kill in module nt:

kill(...)
    kill(pid, sig)
    
    Kill a process with a signal.

>>> 

pid為進程號, sig為信號

import os
import signal
import time

def signal_usr1(signum, frame):
    "Callback invoked when a signal is received"
    pid = os.getpid()
    print 'Received USR1 in process %s' % pid

print 'Forking...'
child_pid = os.fork()
if child_pid:
    print 'PARENT: Pausing before sending signal...'
    time.sleep(1)
    print 'PARENT: Signaling %s' % child_pid
    os.kill(child_pid, signal.SIGUSR1)
else:
    print 'CHILD: Setting up a signal handler'
    signal.signal(signal.SIGUSR1, signal_usr1)
    print 'CHILD: Pausing to wait for signal'
    time.sleep(5)

父進程使用kill()和signal模塊向子進程發送信號。在父進程中,使用kill()發送一個USR1信號之前會暫停很短一段時間,這個短暫的暫停使子進程有時間建立信號處理程序。

=================================================================

signal.pause()

官方文檔:

signal. pause ()

Cause the process to sleep until a signal is received; the appropriate handler will then be called. Returns nothing. Not on Windows. (See the Unix man page signal(2).)

等待直到接收一個信號

import signal
import os 
import time

def do_exit(sig, stack):
    raise SystemExit('Exiting')

# 將SIGINT的默認處理程序替換為SIG_IGN
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGUSR1, do_exit)

print 'My PID:', os.getpid()

signal.pause()

 

正常情況下,SIGINT會產生一個KeyboardInterrupt,這個例子將忽略SIGINT,並在發現SIGUSR1時產生一個SystemExit。

=================================================================

signal.alarm(time)

官方文檔:
signal. alarm (time)

If time is non-zero, this function requests that a SIGALRM signal be sent to the process in time seconds. Any previously scheduled alarm is canceled (only one alarm can be scheduled at any time). The returned value is then the number of seconds before any previously set alarm was to have been delivered. If time is zero, no alarm is scheduled, and any scheduled alarm is canceled. If the return value is zero, no alarm is currently scheduled. (See the Unix man page alarm(2).) Availability: Unix.

如果time是非0,這個函數則響應一個SIGALRM信號並在time秒后發送到該進程。

import signal
import time

def received_alarm(signum, stack):
    print 'Alarm:', time.ctime()

# Call receive_alarm in seconds
signal.signal(signal.SIGALRM, received_alarm)
signal.alarm(2)

print 'Before:', time.ctime()
time.sleep(4)
print 'After:', time.ctime()

================================================================

 

 

 


免責聲明!

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



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