2010-03-31 18 views
34

¿Hay alguna forma de asignar un número de señal (por ejemplo, signal.SIGINT) a su nombre respectivo (es decir, "SIGINT")?Obtener nombres de señales de números en Python

me gustaría ser capaz de imprimir el nombre de una señal en el registro cuando lo reciba, sin embargo no puedo encontrar un mapa de números de señal de nombres en Python, es decir:

import signal 
def signal_handler(signum, frame): 
    logging.debug("Received signal (%s)" % sig_names[signum]) 

signal.signal(signal.SIGINT, signal_handler) 

Para algunos sig_names diccionario, por lo que cuando el proceso recibe SIGINT imprime:

Received signal (SIGINT) 

Respuesta

27

no hay ninguna, pero si no te importa un poco de corte, se puede generar de esta manera:

import signal 
dict((k, v) for v, k in reversed(sorted(signal.__dict__.items())) 
    if v.startswith('SIG') and not v.startswith('SIG_')) 
+0

Estrictamente hablando, esto va a asignar 1 a '' SIG_IGN' y SIGHUP' en la mayoría de plataformas, así que supongo que la prueba debe ser si 'v.startswith ('SIG') y no v.startswith ('SIG _') '. –

+0

También asigna dos veces 6 a 'SIGABRT' y' SIGIOT' en Mac OS X (aunque se podrían usar intercambiablemente, supongo, a diferencia de 'SIG_IGN', que no es una señal). –

+0

@Brian: muy cierto ... por el momento no es una solución perfecta. Pero al menos es algo independiente de la plataforma. – Wolph

0

Bueno, help(signal) dice en la parte inferior:

DATA 
    NSIG = 23 
    SIGABRT = 22 
    SIGBREAK = 21 
    SIGFPE = 8 
    SIGILL = 4 
    SIGINT = 2 
    SIGSEGV = 11 
    SIGTERM = 15 
    SIG_DFL = 0 
    SIG_IGN = 1 

así que esto debería funcionar:

sig_names = {23:"NSIG", 22:"SIGABRT", 21:"SIGBREAK", 8:"SIGFPE", 4:"SIGILL", 
      2:"SIGINT", 11:"SIGSEGV", 15:"SIGTERM", 0:"SIG_DFL", 1:"SIG_IGN"} 
+3

Desafortunadamente, las diferentes plataformas tienen diferentes números de señal, por lo que no es portátil. Gracias, sin embargo. –

+1

Por ejemplo, aquí está el X 'ayuda Mac OS (señal)': SIGABRT = 6 SIGALRM = 14 SIGBUS = 10 SIGCHLD = 20 SIGCONT = 19 SIGEMT = 7 SIGFPE = 8 SIGHUP = 1 SIGILL = 4 SIGINFO = 29 SIGINT = 2 SIGIO = 23 SIGIOT = 6 SIGKILL = 9 SIGPIPE = 13 SIGPROF = 27 SIGQUIT = 3 SIGSEGV = 11 SIGSTOP = 17 SIGSYS = 12 SIGTERM =SIGTRAP = 5 SIGTSTP = 18 SIGTTIN = 21 SIGTTOU = 22 SIGURG = 16 SIGUSR1 = 30 SIGUSR2 = 31 SIGVTALRM = 26 SIGWINCH = 28 SIGXCPU = 24 SIGXFSZ = 25 –

+1

Ah - Realmente debería Me he dado cuenta de eso, considerando todo, especialmente porque he experimentado cuántas señales diferentes hay en Windows y Linux. La solución de WoLpH es más limpia de todos modos :) –

2

He encontrado este artículo cuando estaba en la misma situación y pensó que el controlador sólo está manejando una señal a la vez, por lo que ni siquiera necesita un diccionario general, sólo el nombre de una señal:

sig_name = tuple((v) for v, k in signal.__dict__.iteritems() if k == signum)[0] 

es probable que haya una notación que no necesita el bit tupla (...) [0], pero parece que no puedo resolverlo.

+0

signame = [v para v, k en la señal .__ dict __. Iteritems() si k == signo] [0] funciona bien. – dwelch91

+2

"signame = next (v para v, k en signal .__ dict __. Iteritems() si k == signum)" se detiene cuando lo encuentra en lugar de continuar por el resto del dict (también, no tiene [ 0] que @ssc no le gustó: D). – CryingCyclops

+0

Si se supone que v, k representan claves y valores, los nombres deben invertirse, p. sig_name = tuple ((k) para k, v en la señal .__ dict __. Iteritems() si v == signum) [0] Pero luego hay otros valores en la señal dict cuyo valor puede coincidir con v, en cuyo caso Dependiendo del orden en que iteritems() devuelva elementos, puede imprimir un nombre sin sentido. – tbc0

12

El Python Standard Library Por ejemplo muestra esta función en el capítulo de señales:

SIGNALS_TO_NAMES_DICT = dict((getattr(signal, n), n) \ 
    for n in dir(signal) if n.startswith('SIG') and '_' not in n) 

A continuación, puede utilizar de esta manera:

print "Terminated by signal %s" % SIGNALS_TO_NAMES_DICT[signal_number] 
+2

o (tal vez un poco más preferible) 'SIGNALS_TO_NAMES_DICT.get (signal_number," Señal sin nombre:% d "% signal_number)' –

+0

Esta es una mejor respuesta y debe ser aceptada. – kevinarpe

+0

Como señala @Wolph en su respuesta, esta solución no garantiza un nombre consistente para duplicar señales. – tbc0

27

Con la adición de la signal.Signalsenum en Python 3.5 esto es ahora tan fácil como:

>>> import signal 
>>> signal.SIGINT.name 
'SIGINT' 
>>> signal.SIGINT.value 
2 
>>> signal.Signals(2).name 
'SIGINT' 
>>> signal.Signals['SIGINT'].value 
2 
+1

Esta es una gran respuesta para los usuarios de Py3. –

0

B uilding en another answer:

import signal 

if hasattr(signal, "Signals"): 
    def _signal_name(signum): 
     try: 
      return signal.Signals(signum).name 
     except ValueError: 
      pass 
else: 
    def _signal_name(signum): 
     for n, v in sorted(signal.__dict__.items()): 
      if v != signum: 
       continue 
      if n.startswith("SIG") and not n.startswith("SIG_"): 
       return n 

def signal_name(signum): 
    if signal.SIGRTMIN <= signum <= signal.SIGRTMAX: 
     return "SIGRTMIN+{}".format(signum - signal.SIGRTMIN) 
    x = _signal_name(signum) 
    if x is None: 
     # raise ValueError for invalid signals 
     signal.getsignal(signum) 
     x = "<signal {}>".format(signum) 
    return x