2010-01-27 26 views
21

在Linux下的Python 2.6,我可以使用以下方法來處理TERM信號:Python的 - 捕獲所有信號

import signal 
def handleSigTERM(): 
    shutdown() 
signal.signal(signal.SIGTERM, handleSigTERM)  

有什麼辦法來設置由進程接收的所有信號的處理,比其他一次只設置一次?

+4

我相信答案會是「否」,某些信號甚至不能被捕獲(SIGKILL)。 – 2010-01-27 17:22:32

回答

25

您可以循環訪問信號模塊中的信號並設置它們。

for i in [x for x in dir(signal) if x.startswith("SIG")]: 
    try: 
    signum = getattr(signal,i) 
    signal.signal(signum,sighandler) 
    except (OSError, RuntimeError) as m: #OSError for Python3, RuntimeError for 2 
    print ("Skipping {}".format(i)) 
+0

正是我在找的,謝謝! – 2010-01-27 17:51:39

+0

不客氣。感謝您修復程序中的錯誤。 :) – 2010-01-27 17:54:07

+4

這應該是RuntimeError,而不是RunTimeError。無法編輯,只是一個字符的變化。 – tobych 2011-09-01 04:14:55

10

如果你想擺脫這種嘗試,只需忽略無法捕獲的信號。

#!/usr/bin/env python 
# https://stackoverflow.com/questions/2148888/python-trap-all-signals 
import os 
import sys 
import time 
import signal 

SIGNALS_TO_NAMES_DICT = dict((getattr(signal, n), n) \ 
    for n in dir(signal) if n.startswith('SIG') and '_' not in n) 


def receive_signal(signum, stack): 
    if signum in [1,2,3,15]: 
     print 'Caught signal %s (%s), exiting.' % (SIGNALS_TO_NAMES_DICT[signum], str(signum)) 
     sys.exit() 
    else: 
     print 'Caught signal %s (%s), ignoring.' % (SIGNALS_TO_NAMES_DICT[signum], str(signum)) 

def main(): 
    uncatchable = ['SIG_DFL','SIGSTOP','SIGKILL'] 
    for i in [x for x in dir(signal) if x.startswith("SIG")]: 
     if not i in uncatchable: 
      signum = getattr(signal,i) 
      signal.signal(signum,receive_signal) 
    print('My PID: %s' % os.getpid()) 
    while True: 
     time.sleep(1) 
main() 
+0

代碼沒有正確縮進,但我無法編輯它,因爲不要讓我做出那麼小的更改。所有的for應該縮進一個縮進級別。 – krenel00 2013-05-10 15:04:55

-1

該代碼不適用於當前版本的python。以SIG開頭的變量有許多相同的值。例如,SIGHUP和SIG_UNBLOCK都是1.我能想到得到實際信號列表的唯一方法就是自己做。

from signal import *  
signals = { 
     SIGABRT: 'SIGABRT', 
     SIGALRM: 'SIGALRM', 
     SIGBUS: 'SIGBUS', 
     SIGCHLD: 'SIGCHLD', 
     SIGCONT: 'SIGCONT', 
     SIGFPE: 'SIGFPE', 
     SIGHUP: 'SIGHUP', 
     SIGILL: 'SIGILL', 
     SIGINT: 'SIGINT', 
     SIGPIPE: 'SIGPIPE', 
     SIGPOLL: 'SIGPOLL', 
     SIGPROF: 'SIGPROF', 
     SIGQUIT: 'SIGQUIT', 
     SIGSEGV: 'SIGSEGV', 
     SIGSYS: 'SIGSYS', 
     SIGTERM: 'SIGTERM', 
     SIGTRAP: 'SIGTRAP', 
     SIGTSTP: 'SIGTSTP', 
     SIGTTIN: 'SIGTTIN', 
     SIGTTOU: 'SIGTTOU', 
     SIGURG: 'SIGURG', 
     SIGUSR1: 'SIGUSR1', 
     SIGUSR2: 'SIGUSR2', 
     SIGVTALRM: 'SIGVTALRM', 
     SIGXCPU: 'SIGXCPU', 
     SIGXFSZ: 'SIGXFSZ', 
     } 

for num in signals: 
    signal(num, h) 
+0

這沒有必要。所有的信號仍然以'SIG'開始,但你需要添加一個雙重檢查以確保你忽略了'SIG_'。 – 2017-05-26 11:25:12

8

對於Python 3.5,信號常數defined as an enum,實現了更好的途徑:

import signal 

catchable_sigs = set(signal.Signals) - {signal.SIGKILL, signal.SIGSTOP} 
for sig in catchable_sigs: 
    signal.signal(sig, print) # Substitute handler of choice for `print` 
+0

請問downvoter請留言?這個答案有什麼問題嗎? – doctaphred 2016-04-23 11:15:14

1

這裏的不作爲有許多陷阱的其他2/3兼容的方式:

from itertools import count 
import signal 

def set_all_signal_signals(handler): 
    """Set all signals to a particular handler.""" 
    for signalnum in count(1): 
     try: 
      signal.signal(signalnum, handler) 
      print("set {}".format(signalnum)) 
     except (OSError, RuntimeError): 
      # Invalid argument such as signals that can't be blocked 
      pass 
     except ValueError: 
      # Signal out of range 
      break 

由於signalnum只是一個數字,所以迭代超過1將信號設置爲特定的句柄。