2010-01-27 13 views
21

en Python 2.6 en Linux, que puede usar lo siguiente para manejar una señal TERM:Python - trampa de todas las señales

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

¿Hay alguna manera de configurar un controlador para todas las señales recibidas por el proceso, que no sea simplemente configurándolos uno a la vez?

+4

La respuesta creo que va a ser "no" y cierta señal ni siquiera puede quedar atrapada (SIGKILL). –

Respuesta

25

Puede recorrer las señales en el módulo de señal y configurarlas.

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

¡Justo lo que estaba buscando, gracias! –

+0

De nada. Gracias por arreglar el error en el programa. :) –

+4

Eso debería ser RuntimeError, no RunTimeError. no se pudo editar, ya que solo un cambio de personaje. – tobych

10

Si quieres deshacerte de la prueba, simplemente ignora las señales que no se pueden atrapar.

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

El código no está adecuadamente sangrado, pero no puedo editarlo porque SO no me permite hacer un cambio tan pequeño. Todo el texto debe sangrarse con un nivel de sangría menor. – krenel00

-1

Ese código no funcionará en la versión actual del pitón. Hay muchas variables que comienzan con SIG con el mismo valor. Por ejemplo, SIGHUP y SIG_UNBLOCK son ambos 1. La única forma en que podía pensar en obtener una lista de señales reales era hacerlo yo mismo.

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

No es necesario. Todas las señales aún comienzan con 'SIG', pero debes agregar una doble comprobación para asegurarte de que ignoras las' SIG_'. –

8

A partir de Python 3.5, las constantes de señal son defined as an enum, lo que permite un enfoque más agradable:

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

¿Podría el infractor por favor dejar un comentario? ¿Hay algo mal con esta respuesta? – doctaphred

1

una manera compatible 2/3 que no tiene tantas trampas como los demás aquí:

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 

Dado que signalnum es solo un número, repita más de 1 fuera de rango, configurando la señal en un mango específico.

Cuestiones relacionadas