Python - Trap all signals

前端 未结 8 1381
慢半拍i
慢半拍i 2020-11-30 04:54

In python 2.6 under Linux, I can use the following to handle a TERM signal:

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


        
相关标签:
8条回答
  • 2020-11-30 05:09

    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()
    
    0 讨论(0)
  • 2020-11-30 05:11

    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`
    
    0 讨论(0)
  • 2020-11-30 05:14

    For Python 3:

    for sig in signal.Signals:
        try:
            signal.signal(sig, sighandler)
        except OSError:
            print('Skipping', sig)
    
    0 讨论(0)
  • 2020-11-30 05:14

    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)
    
    0 讨论(0)
  • 2020-11-30 05:15

    In Python3.8 we've got a new function signal.valid_signals() https://docs.python.org/3/library/signal.html#signal.valid_signals

    import signal
    for sig in signal.valid_signals():
        print(f"{sig:2d}",sig)
    
    0 讨论(0)
  • 2020-11-30 05:19

    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))
    
    0 讨论(0)
提交回复
热议问题