Python - 捕获所有信号

Jus*_*ier 24 python linux signal-handling

在Linux下的python 2.6中,我可以使用以下内容来处理TERM信号:

import signal
def handleSigTERM():
    shutdown()
signal.signal(signal.SIGTERM, handleSigTERM)    
Run Code Online (Sandbox Code Playgroud)

有没有办法为进程收到的所有信号设置处理程序,而不是一次一个地设置它们?

Nou*_*him 33

您可以循环浏览信号模块中的信号并进行设置.

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))
Run Code Online (Sandbox Code Playgroud)

  • 那应该是RuntimeError,而不是RunTimeError.无法编辑,因为只有一个字符更改. (4认同)
  • 您的列表理解将包括“SIG_IGN”,这是一个动作而不是一个信号。由于此操作的“值”对应于“1”,即“SIGHUP”的值,因此您将设置此信号两次。对于这种无关紧要的特定情况,但是此代码可能会因其他类似目的而分解。 (2认同)

doc*_*red 16

从Python 3.5开始,信号常量被定义为枚举,从而实现更好的方法:

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`
Run Code Online (Sandbox Code Playgroud)


小智 11

如果你想摆脱尝试,只需忽略无法捕获的信号.

#!/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()
Run Code Online (Sandbox Code Playgroud)