Linuxのpython 2.6では、以下を使用してTERMシグナルを処理できます。
import signal
def handleSigTERM():
shutdown()
signal.signal(signal.SIGTERM, handleSigTERM)
一度に1つずつ設定する以外に、プロセスが受信したすべてのシグナルのハンドラーを設定する方法はありますか?
シグナルモジュール内のシグナルをループしてセットアップするだけです。
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))
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`
試行を取り除きたい場合は、キャッチできない信号を無視してください。
#!/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()
Windows10および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
結果:
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
これは、他の方法ほど多くの落とし穴がない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を繰り返して範囲外になり、信号を特定のハンドルに設定します。
Python 3:
for sig in signal.Signals:
try:
signal.signal(sig, sighandler)
except OSError:
print('Skipping', sig)