Python - Trap all signals

不问归期 提交于 2019-11-27 04:23:32

You could just loop through the signals in the signal module and set them up.

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))

As of Python 3.5, the signal constants are defined as an enum, enabling a nicer approach:

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`
eric poelke

If you want to get rid of the try, just ignore signals that cannot be caught.

#!/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()

Here's a 2/3 compatible way which doesn't have as many pitfalls as the others:

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

Since signalnum is just a number, iterate over 1 to out of range setting the signal to a particular handle.

Works on Windows 10 and Python 3.7:

import signal
import time

def sighandler(signal,frame):
    print("signal",sig,frame)
    return

catchable_sigs = set(signal.Signals)
for sig in catchable_sigs:
    try:
        signal.signal(sig, sighandler)
        print("Setting ",sig)
        print ("value {}".format(sig))
    except (ValueError, OSError, RuntimeError) as m:
        print("Skipping ",sig)
        print ("Value {}".format(sig))


# press some keys or issue kill
x = 0
while x < 5:
    time.sleep(4)
    x += 1

Results:

Skipping  Signals.CTRL_C_EVENT
Value 0
Skipping  Signals.CTRL_BREAK_EVENT
Value 1
Setting  Signals.SIGINT
value 2
Setting  Signals.SIGILL
value 4
Setting  Signals.SIGFPE
value 8
Setting  Signals.SIGSEGV
value 11
Setting  Signals.SIGTERM
value 15
Setting  Signals.SIGBREAK
value 21
Setting  Signals.SIGABRT
value 22
enigmaticPhysicist

That code won't work in the current version of python. There are many variables starting with SIG with the same value. For instance, SIGHUP and SIG_UNBLOCK are both 1. The only way I could think of to get a list of actual signals was to just make it myself.

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)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!