¿Hay alguna manera de evitar que se capture una excepción SystemExit provocada por sys.exit ()?

StackOverflow https://stackoverflow.com/questions/173278

Pregunta

Los documentos dicen que llamar a sys.exit () genera una excepción de SystemExit que se puede detectar en niveles externos. Tengo una situación en la que quiero salir de forma definitiva e incuestionable desde el interior de un caso de prueba, sin embargo, el módulo unittest detecta SystemExit e impide la salida. Normalmente esto es genial, pero la situación específica que estoy tratando de manejar es una en la que nuestro marco de prueba ha detectado que está configurado para apuntar a una base de datos que no es de prueba. En este caso, quiero salir e impedir que se ejecuten más pruebas. Por supuesto, desde que Unittest atrapa el SystemExit y continúa feliz por su camino, me está frustrando.

La única opción que he pensado hasta ahora es usar ctypes o algo similar para llamar a exit (3) directamente, pero esto parece un truco bastante fugitivo para algo que debería ser realmente simple.

¿Fue útil?

Solución

Puede llamar a os._exit () para salir directamente, sin lanzar una excepción:

import os
os._exit(1)

Esto omite toda la lógica de apagado de Python, como el módulo atexit , y no se ejecutará a través de la lógica de manejo de excepciones que está tratando de evitar en esta situación. El argumento es el código de salida que devolverá el proceso.

Otros consejos

Como dijo Jerub, os._exit (1) es su respuesta. Pero, teniendo en cuenta que omite todos los procedimientos de limpieza de , incluidos los bloques por último: , los archivos de cierre, etc. ish " forma de usarlo?

Si su problema es que SystemExit está siendo capturado en niveles externos (es decir, prueba de unidad), entonces ¡sea el nivel externo usted mismo! Envuelva su principal código en un bloque try / except, captura SystemExit y llama a os._exit allí, y solo allí! De esta manera puedes llamar a sys.exit normalmente en cualquier parte del código, deje que salga al nivel superior, cierre con gracia todos los archivos y ejecute todas las limpiezas, y luego llame a os._exit.

Incluso puede elegir qué salidas son la "emergencia". unos El siguiente código es un ejemplo de tal enfoque:

import sys, os

EMERGENCY = 255  # can be any number actually

try:
    # wrap your whole code here ...
    # ... some code
    if x: sys.exit()
    # ... some more code
    if y: sys.exit(EMERGENCY)  # use only for emergency exits
    # ...
except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it
    else:
        os._exit(EMERGENCY)  # try to stop *that*, sucker!
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top