Este módulo proporciona mecanismos para usar controladores de señales en Python.
Reglas generales
los signal.signal()
La función permite definir manejadores personalizados que se ejecutarán cuando se reciba una señal. Se instalan una pequeña cantidad de controladores predeterminados: SIGPIPE
se ignora (por lo que los errores de escritura en tuberías y sockets se pueden informar como excepciones normales de Python) y SIGINT
se traduce en un KeyboardInterrupt
excepción si el proceso padre no lo ha cambiado.
Un controlador para una señal en particular, una vez configurado, permanece instalado hasta que se restablece explícitamente (Python emula la interfaz de estilo BSD independientemente de la implementación subyacente), con la excepción del controlador para SIGCHLD
, que sigue a la implementación subyacente.
Ejecución de manejadores de señales de Python
Un manejador de señales de Python no se ejecuta dentro del manejador de señales de bajo nivel (C). En cambio, el manejador de señales de bajo nivel establece una bandera que le dice al máquina virtual para ejecutar el controlador de señal de Python correspondiente en un punto posterior (por ejemplo, en el siguiente bytecode instrucción). Esto tiene consecuencias:
- No tiene mucho sentido detectar errores sincrónicos como
SIGFPE
oSIGSEGV
que son causados por una operación no válida en código C. Python volverá del manejador de señales al código C, que probablemente genere la misma señal nuevamente, causando que Python aparentemente se cuelgue. Desde Python 3.3 en adelante, puede usar elfaulthandler
módulo para informar sobre errores síncronos. - Un cálculo de larga duración implementado exclusivamente en C (como la coincidencia de expresiones regulares en un gran cuerpo de texto) puede ejecutarse ininterrumpidamente durante un período de tiempo arbitrario, independientemente de las señales recibidas. Se llamará a los controladores de señales de Python cuando finalice el cálculo.
Señales e hilos
Los manejadores de señales de Python siempre se ejecutan en el hilo principal de Python del intérprete principal, incluso si la señal se recibió en otro hilo. Esto significa que las señales no se pueden utilizar como medio de comunicación entre subprocesos. Puede utilizar las primitivas de sincronización de la threading
módulo en su lugar.
Además, solo el hilo principal del intérprete principal puede establecer un nuevo controlador de señales.
Contenidos del módulo
Modificado en la versión 3.5: señal (SIG *), manejador (SIG_DFL
, SIG_IGN
) y sigmask (SIG_BLOCK
, SIG_UNBLOCK
, SIG_SETMASK
) las constantes relacionadas enumeradas a continuación se convirtieron en enums
. getsignal()
, pthread_sigmask()
, sigpending()
y sigwait()
las funciones devuelven legibles por humanos enums
.
Las variables definidas en el signal
módulo son:
signal.SIG_DFL
-
Ésta es una de las dos opciones estándar de manejo de señales; simplemente realizará la función predeterminada para la señal. Por ejemplo, en la mayoría de los sistemas, la acción predeterminada para
SIGQUIT
es volcar el núcleo y salir, mientras que la acción predeterminada paraSIGCHLD
es simplemente ignorarlo.
signal.SIG_IGN
-
Este es otro manejador de señales estándar, que simplemente ignorará la señal dada.
signal.SIGABRT
-
Abortar señal de abortar (3).
signal.SIGALRM
-
Señal de temporizador de alarma (2).
Disponibilidad: Unix.
signal.SIGBREAK
-
Interrumpir desde el teclado (CTRL + BREAK).
Disponibilidad: Windows.
signal.SIGBUS
-
Error de bus (mal acceso a la memoria).
Disponibilidad: Unix.
signal.SIGCHLD
-
El proceso hijo se detuvo o terminó.
Disponibilidad: Unix.
signal.SIGCLD
-
Alias para
SIGCHLD
.
signal.SIGCONT
-
Continuar el proceso si está detenido actualmente
Disponibilidad: Unix.
signal.SIGFPE
-
Excepción de coma flotante. Por ejemplo, división por cero.
Ver también
ZeroDivisionError
se genera cuando el segundo argumento de una operación de división o módulo es cero.
signal.SIGHUP
-
Se detectó un bloqueo en el terminal de control o muerte del proceso de control.
Disponibilidad: Unix.
signal.SIGILL
-
Instrucción ilegal.
signal.SIGINT
-
Interrumpir desde el teclado (CTRL + C).
La acción predeterminada es subir
KeyboardInterrupt
.
signal.SIGKILL
-
Señal de muerte.
No se puede capturar, bloquear o ignorar.
Disponibilidad: Unix.
signal.SIGPIPE
-
Tubería rota: escriba en la tubería sin lectores.
La acción predeterminada es ignorar la señal.
Disponibilidad: Unix.
signal.SIGSEGV
-
Fallo de segmentación: referencia de memoria no válida.
signal.SIGTERM
-
Señal de terminación.
signal.SIGUSR1
-
Señal definida por el usuario 1.
Disponibilidad: Unix.
signal.SIGUSR2
-
Señal definida por el usuario 2.
Disponibilidad: Unix.
signal.SIGWINCH
-
Señal de cambio de tamaño de ventana.
Disponibilidad: Unix.
SIG*
-
Todos los números de señal se definen simbólicamente. Por ejemplo, la señal de colgar se define como
signal.SIGHUP
; los nombres de las variables son idénticos a los nombres utilizados en los programas C, como se encuentran en
. La página de manual de Unix para ‘signal()
‘enumera las señales existentes (en algunos sistemas esto es señal (2), en otros la lista está en señal (7)). Tenga en cuenta que no todos los sistemas definen el mismo conjunto de nombres de señales; Este módulo solo define los nombres definidos por el sistema.
signal.CTRL_C_EVENT
-
La señal correspondiente a la Ctrl + C evento de pulsación de tecla. Esta señal solo se puede utilizar con
os.kill()
.Disponibilidad: Windows.
Nuevo en la versión 3.2.
signal.CTRL_BREAK_EVENT
-
La señal correspondiente a la Ctrl + Pausa evento de pulsación de tecla. Esta señal solo se puede utilizar con
os.kill()
.Disponibilidad: Windows.
Nuevo en la versión 3.2.
signal.NSIG
-
Uno más que el número de la señal más alta.
signal.ITIMER_REAL
-
Disminuye el temporizador de intervalos en tiempo real y entrega
SIGALRM
al vencimiento.
signal.ITIMER_VIRTUAL
-
Reduce el temporizador de intervalo solo cuando el proceso se está ejecutando y entrega SIGVTALRM al expirar.
signal.ITIMER_PROF
-
Disminuye el temporizador de intervalo tanto cuando el proceso se ejecuta como cuando el sistema se está ejecutando en nombre del proceso. Junto con ITIMER_VIRTUAL, este temporizador generalmente se usa para perfilar el tiempo que pasa la aplicación en el espacio del usuario y del kernel. SIGPROF se entrega al vencimiento.
signal.SIG_BLOCK
-
Un posible valor para el cómo parámetro a
pthread_sigmask()
indicando que las señales deben bloquearse.Nuevo en la versión 3.3.
signal.SIG_UNBLOCK
-
Un posible valor para el cómo parámetro a
pthread_sigmask()
indicando que las señales deben ser desbloqueadas.Nuevo en la versión 3.3.
signal.SIG_SETMASK
-
Un posible valor para el cómo parámetro a
pthread_sigmask()
indicando que la máscara de señal debe ser reemplazada.Nuevo en la versión 3.3.
los signal
módulo define una excepción:
exception signal.ItimerError
-
Criado para señalar un error del subyacente
setitimer()
ogetitimer()
implementación. Espere este error si se pasa un temporizador de intervalo no válido o un tiempo negativo asetitimer()
. Este error es un subtipo deOSError
.Nuevo en la versión 3.3: Este error solía ser un subtipo de
IOError
, que ahora es un alias deOSError
.
los signal
módulo define las siguientes funciones:
signal.alarm(time)
-
Si tiempo no es cero, esta función solicita que un
SIGALRM
la señal sea enviada al proceso en tiempo segundos. Se cancela cualquier alarma programada previamente (solo se puede programar una alarma en cualquier momento). El valor devuelto es entonces el número de segundos antes de que se entregue cualquier alarma configurada previamente. Si tiempo es cero, no hay ninguna alarma programada y cualquier alarma programada se cancela. Si el valor de retorno es cero, no hay ninguna alarma programada actualmente.Disponibilidad: Unix. Ver la página del manual alarma (2) para mayor información.
signal.getsignal(signalnum)
-
Devuelve el manejador de señal actual para la señal. signalnum. El valor devuelto puede ser un objeto de Python invocable o uno de los valores especiales
signal.SIG_IGN
,signal.SIG_DFL
oNone
. Aquí,signal.SIG_IGN
significa que la señal fue previamente ignorada,signal.SIG_DFL
significa que la forma predeterminada de manejar la señal estaba en uso anteriormente, yNone
significa que el controlador de señales anterior no se instaló desde Python.
signal.strsignal(signalnum)
-
Devuelve la descripción del sistema de la señal signalnum, como “Interrupción”, “Fallo de segmentación”, etc.
None
si no se reconoce la señal.Nuevo en la versión 3.8.
signal.valid_signals()
-
Devuelve el conjunto de números de señal válidos en esta plataforma. Esto puede ser menor que
range(1, NSIG)
si algunas señales están reservadas por el sistema para uso interno.Nuevo en la versión 3.8.
signal.pause()
-
Hacer que el proceso duerma hasta que se reciba una señal; entonces se llamará al manejador apropiado. No devuelve nada.
Disponibilidad: Unix. Ver la página del manual señal (2) para mayor información.
Ver también
sigwait()
,sigwaitinfo()
,sigtimedwait()
ysigpending()
.
signal.raise_signal(signum)
-
Envía una señal al proceso de llamada. No devuelve nada.
Nuevo en la versión 3.8.
signal.pidfd_send_signal(pidfd, sig, siginfo=None, flags=0)
-
Enviar señal sig al proceso al que se refiere el descriptor de archivo pidfd. Python actualmente no es compatible con siginfo parámetro; debe ser
None
. los banderas se proporciona un argumento para futuras extensiones; actualmente no hay valores de bandera definidos.Ver el pidfd_send_signal (2) man page para obtener más información.
Disponibilidad: Linux 5.1 o superior
Nuevo en la versión 3.9.
signal.pthread_kill(thread_id, signalnum)
-
Envía la señal signalnum al hilo thread_id, otro hilo en el mismo proceso que la persona que llama. El hilo de destino puede ejecutar cualquier código (Python o no). Sin embargo, si el hilo de destino está ejecutando el intérprete de Python, los manejadores de señales de Python serán ejecutado por el hilo principal del intérprete principal. Por lo tanto, el único punto de enviar una señal a un hilo de Python en particular sería forzar una llamada al sistema en ejecución para fallar con
InterruptedError
.Usar
threading.get_ident()
o laident
atributo dethreading.Thread
objetos para obtener un valor adecuado para thread_id.Si signalnum es 0, entonces no se envía ninguna señal, pero aún se realiza la verificación de errores; esto puede ser se utiliza para comprobar si el hilo de destino todavía se está ejecutando.
Plantea un evento de auditoría
signal.pthread_kill
con argumentosthread_id
,signalnum
.Disponibilidad: Unix. Ver la página del manual pthread_kill (3) para mayor información.
Ver también
os.kill()
.Nuevo en la versión 3.3.
signal.pthread_sigmask(how, mask)
-
Busque y / o cambie la máscara de señal del hilo de llamada. La máscara de señal es el conjunto de señales cuya entrega está actualmente bloqueada para la persona que llama. Devuelve la máscara de señal anterior como un conjunto de señales.
El comportamiento de la llamada depende del valor de cómo, como sigue.
SIG_BLOCK
: El conjunto de señales bloqueadas es la unión del conjunto actual y el máscara argumento.SIG_UNBLOCK
: Las señales en máscara se eliminan del conjunto actual de señales bloqueadas. Está permitido intentar desbloquear una señal que no esté bloqueada.SIG_SETMASK
: El conjunto de señales bloqueadas se establece en máscara argumento.
máscara es un conjunto de números de señal (por ejemplo,
signal.SIGINT
,signal.SIGTERM
). Usarvalid_signals()
para una máscara completa que incluye todas las señales.Por ejemplo,
signal.pthread_sigmask(signal.SIG_BLOCK, [])
lee la máscara de señal del hilo de llamada.SIGKILL
ySIGSTOP
no se puede bloquear.Disponibilidad: Unix. Ver la página del manual sigprocmask (3) y pthread_sigmask (3) para mayor información.
Ver también
pause()
,sigpending()
ysigwait()
.Nuevo en la versión 3.3.
signal.setitimer(which, seconds, interval=0.0)
-
Establece el temporizador de intervalo dado (uno de
signal.ITIMER_REAL
,signal.ITIMER_VIRTUAL
osignal.ITIMER_PROF
) especificado por cuales disparar después segundos (se acepta flotador, diferente dealarm()
) y después de eso cada intervalo segundos (si intervalo es distinto de cero). El temporizador de intervalo especificado por cuales se puede borrar configurando segundos a cero.Cuando se dispara un temporizador de intervalos, se envía una señal al proceso. La señal enviada depende del temporizador que se utilice;
signal.ITIMER_REAL
entregaráSIGALRM
,signal.ITIMER_VIRTUAL
envíaSIGVTALRM
, ysignal.ITIMER_PROF
entregaráSIGPROF
.Los valores antiguos se devuelven como una tupla: (retraso, intervalo).
Si intenta pasar un temporizador de intervalo no válido, se producirá una
ItimerError
.Disponibilidad: Unix.
signal.getitimer(which)
-
Devuelve el valor actual de un temporizador de intervalo dado especificado por cuales.
Disponibilidad: Unix.
signal.set_wakeup_fd(fd, *, warn_on_full_buffer=True)
-
Establezca el descriptor del archivo de activación en fd. Cuando se recibe una señal, el número de la señal se escribe como un solo byte en el fd. Esto puede ser utilizado por una biblioteca para despertar una encuesta o seleccionar una llamada, permitiendo que la señal se procese por completo.
Se devuelve el fd de activación anterior (o -1 si la activación del descriptor de archivo no estaba habilitada). Si fd es -1, la activación del descriptor de archivo está deshabilitada. Si no es -1, fd debe ser no bloqueante. Depende de la biblioteca eliminar los bytes de fd antes de llamar a la encuesta o seleccionar de nuevo.
Cuando los subprocesos están habilitados, esta función solo se puede llamar desde el hilo principal del intérprete principal; intentar llamarlo desde otros hilos provocará un
ValueError
excepción que se planteará.Hay dos formas habituales de utilizar esta función. En ambos enfoques, usa el fd para despertar cuando llega una señal, pero luego difieren en cómo determinan cuales ha llegado la señal o señales.
En el primer enfoque, leemos los datos del búfer de fd, y los valores de bytes le dan los números de señal. Esto es simple, pero en casos raros puede surgir un problema: generalmente el fd tendrá una cantidad limitada de espacio en el búfer, y si llegan demasiadas señales demasiado rápido, entonces el búfer puede llenarse y algunas señales pueden perderse. Si usa este enfoque, debe configurar
warn_on_full_buffer=True
, que al menos provocará que se imprima una advertencia en stderr cuando se pierdan las señales.En el segundo enfoque, usamos el wakeup fd solamente para reactivaciones e ignore los valores de bytes reales. En este caso, lo único que nos importa es si el búfer de fd está vacío o no; un búfer lleno no indica ningún problema. Si usa este enfoque, debe configurar
warn_on_full_buffer=False
, para que sus usuarios no se confundan con mensajes de advertencia falsos.Modificado en la versión 3.5: En Windows, la función ahora también admite identificadores de socket.
Modificado en la versión 3.7: Adicional
warn_on_full_buffer
parámetro.
signal.siginterrupt(signalnum, flag)
-
Cambiar el comportamiento de reinicio de la llamada al sistema: si bandera es
False
, las llamadas al sistema se reiniciarán cuando las interrumpa la señal signalnum, de lo contrario se interrumpirán las llamadas al sistema. No devuelve nada.Disponibilidad: Unix. Ver la página del manual siginterrupt (3) para mayor información.
Tenga en cuenta que la instalación de un controlador de señales con
signal()
restablecerá el comportamiento de reinicio a interrumpible llamando implícitamentesiginterrupt()
con un verdadero bandera valor para la señal dada.
signal.signal(signalnum, handler)
-
Establecer el controlador para la señal signalnum a la función manipulador. manipulador puede ser un objeto de Python invocable que toma dos argumentos (ver más abajo), o uno de los valores especiales
signal.SIG_IGN
osignal.SIG_DFL
. Se devolverá el controlador de señal anterior (consulte la descripción degetsignal()
encima). (Consulte la página del manual de Unix señal (2) para mayor información.)Cuando los subprocesos están habilitados, esta función solo se puede llamar desde el hilo principal del intérprete principal; intentar llamarlo desde otros hilos provocará un
ValueError
excepción que se planteará.los manipulador se llama con dos argumentos: el número de señal y el marco de pila actual (
None
o un objeto marco; para obtener una descripción de los objetos de marco, consulte la descripción en la jerarquía de tipos o vea las descripciones de los atributos en elinspect
módulo).En Windows,
signal()
solo se puede llamar conSIGABRT
,SIGFPE
,SIGILL
,SIGINT
,SIGSEGV
,SIGTERM
, oSIGBREAK
. AValueError
se planteará en cualquier otro caso. Tenga en cuenta que no todos los sistemas definen el mismo conjunto de nombres de señales; unAttributeError
se generará si un nombre de señal no se define comoSIG*
constante de nivel de módulo.
signal.sigpending()
-
Examine el conjunto de señales que están pendientes de entrega al hilo de llamada (es decir, las señales que se han generado mientras estaban bloqueadas). Devuelve el conjunto de señales pendientes.
Disponibilidad: Unix. Ver la página del manual pendiente (2) para mayor información.
Ver también
pause()
,pthread_sigmask()
ysigwait()
.Nuevo en la versión 3.3.
signal.sigwait(sigset)
-
Suspender la ejecución del hilo de llamada hasta la entrega de una de las señales especificadas en el conjunto de señales sigset. La función acepta la señal (la elimina de la lista pendiente de señales) y devuelve el número de señal.
Disponibilidad: Unix. Ver la página del manual sigwait (3) para mayor información.
Ver también
pause()
,pthread_sigmask()
,sigpending()
,sigwaitinfo()
ysigtimedwait()
.Nuevo en la versión 3.3.
signal.sigwaitinfo(sigset)
-
Suspender la ejecución del hilo de llamada hasta la entrega de una de las señales especificadas en el conjunto de señales sigset. La función acepta la señal y la elimina de la lista de señales pendientes. Si una de las señales en sigset ya está pendiente para el hilo de llamada, la función volverá inmediatamente con información sobre esa señal. No se llama al gestor de señales para la señal enviada. La función plantea un
InterruptedError
si es interrumpido por una señal que no está en sigset.El valor de retorno es un objeto que representa los datos contenidos en el
siginfo_t
estructura, a saber:si_signo
,si_code
,si_errno
,si_pid
,si_uid
,si_status
,si_band
.Disponibilidad: Unix. Ver la página del manual sigwaitinfo (2) para mayor información.
Ver también
pause()
,sigwait()
ysigtimedwait()
.Nuevo en la versión 3.3.
Modificado en la versión 3.5: La función ahora se vuelve a intentar si se interrumpe por una señal que no está en sigset y el manejador de señales no genera una excepción (ver PEP 475 por la justificación).
signal.sigtimedwait(sigset, timeout)
-
Igual que
sigwaitinfo()
, pero requiere un adicional se acabó el tiempo argumento que especifica un tiempo de espera. Si se acabó el tiempo se especifica como0
, se realiza una encuesta. DevolucionesNone
si ocurre un tiempo de espera.Disponibilidad: Unix. Ver la página del manual sigtimedwait (2) para mayor información.
Ver también
pause()
,sigwait()
ysigwaitinfo()
.Nuevo en la versión 3.3.
Modificado en la versión 3.5: La función ahora se reintenta con el recálculo se acabó el tiempo si es interrumpido por una señal que no está en sigset y el manejador de señales no genera una excepción (ver PEP 475 por la justificación).
Ejemplo
Aquí hay un programa de ejemplo mínimo. Usa el alarm()
función para limitar el tiempo de espera para abrir un archivo; Esto es útil si el archivo es para un dispositivo en serie que puede no estar encendido, lo que normalmente causaría os.open()
colgar indefinidamente. La solución es configurar una alarma de 5 segundos antes de abrir el archivo; si la operación toma demasiado tiempo, se enviará la señal de alarma y el manejador genera una excepción.
import signal, os defhandler(signum, frame):print('Signal handler called with signal', signum)raise OSError("Couldn't open device!")# Set the signal handler and a 5-second alarm signal.signal(signal.SIGALRM, handler) signal.alarm(5)# This open() may hang indefinitely fd = os.open('/dev/ttyS0', os.O_RDWR) signal.alarm(0)# Disable the alarm
Nota sobre SIGPIPE
Canalizando la salida de su programa a herramientas como cabeza (1) causará un SIGPIPE
señal que se enviará a su proceso cuando el receptor de su salida estándar cierre antes. Esto da como resultado una excepción como BrokenPipeError: [Errno 32] Broken pipe
. Para manejar este caso, envuelva su punto de entrada para captar esto excepción de la siguiente manera:
import os import sys defmain():try:# simulate large output (your code replaces this loop)for x inrange(10000):print("y")# flush output here to force SIGPIPE to be triggered# while inside this try block. sys.stdout.flush()except BrokenPipeError:# Python flushes standard streams on exit; redirect remaining output# to devnull to avoid another BrokenPipeError at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) sys.exit(1)# Python exits with error code 1 on EPIPEif __name__ =='__main__': main()
No ajuste SIGPIPE
disposición a SIG_DFL
para evitar BrokenPipeError
. Si lo hace, su programa se cerrará inesperadamente también cuando se interrumpa cualquier conexión de socket mientras su programa todavía está escribiendo en él.
Aquí puedes ver las reseñas y valoraciones de los lectores
Te invitamos a añadir valor a nuestro contenido cooperando tu experiencia en las ilustraciones.