Python - перехватывать все сигналы - PullRequest
23 голосов
/ 27 января 2010

В python 2.6 под Linux я могу использовать следующее для обработки сигнала TERM:

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

Есть ли способ настроить обработчик для всех сигналов, полученных процессом, кроме как устанавливать их по одному?

Ответы [ 6 ]

32 голосов
/ 27 января 2010

Вы можете просто просмотреть сигналы в сигнальном модуле и настроить их.

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))
13 голосов
/ 02 января 2016

Начиная с Python 3.5, константы сигнала определены как enum , что позволяет использовать более приятный подход:

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`
10 голосов
/ 15 апреля 2011

Если вы хотите избавиться от попытки, просто игнорируйте сигналы, которые не могут быть перехвачены.

#!/usr/bin/env python
# /1847607/python-perehvatyvat-vse-signaly
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()
1 голос
/ 17 декабря 2018

Работает в Windows 10 и 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
1 голос
/ 16 мая 2017

Вот 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 для выхода за пределы диапазона, устанавливая сигнал для определенного дескриптора.

0 голосов
/ 12 марта 2015

Этот код не будет работать в текущей версии Python. Есть много переменных, начинающихся с SIG с одинаковым значением. Например, SIGHUP и SIG_UNBLOCK равны 1. Единственный способ, которым я мог придумать, чтобы получить список фактических сигналов , это просто сделать его самому.

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...