可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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, handleSigTERM)
Is there any way to setup a handler for all signals received by the process, other than just setting them up one-at-a-time?
回答1:
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))
回答2:
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()
回答3:
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`
回答4:
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.
回答5:
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)