Esiste un modo per impedire che un'eccezione SystemExit sollevata da sys.exit () venga catturata?
-
05-07-2019 - |
Domanda
I documenti affermano che la chiamata a sys.exit () solleva un'eccezione SystemExit che può essere rilevata nei livelli esterni. Ho una situazione in cui desidero uscire definitivamente e indiscutibilmente dall'interno di un caso di test, tuttavia il modulo unittest cattura SystemExit e impedisce l'uscita. Questo è normalmente fantastico, ma la situazione specifica che sto cercando di gestire è quella in cui il nostro framework di test ha rilevato che è configurato per puntare a un database non di test. In questo caso, desidero uscire e impedire l'esecuzione di ulteriori test. Naturalmente, dato che unittest intrappola SystemExit e continua felicemente sulla sua strada, mi sta contrastando.
L'unica opzione a cui ho pensato finora è usare direttamente i tipi o qualcosa di simile a chiamare exit (3) direttamente, ma questo sembra un hack piuttosto fugace per qualcosa che dovrebbe essere davvero semplice.
Soluzione
Puoi chiamare os._exit ()
per uscire direttamente, senza generare un'eccezione:
import os
os._exit(1)
Questo ignora tutta la logica di spegnimento di Python, come il modulo atexit
, e non scorrerà attraverso la logica di gestione delle eccezioni che stai cercando di evitare in questa situazione. L'argomento è il codice di uscita che verrà restituito dal processo.
Altri suggerimenti
Come ha detto Jerub, os._exit (1)
è la tua risposta. Ma, considerando che ignora le tutte procedure di pulizia, incluso infine:
blocchi, chiusura di file, ecc. E che dovrebbe davvero essere evitato a tutti i costi, posso presentare un " più sicuro- ish " modo di usarlo?
Se il tuo problema è che SystemExit
viene catturato ai livelli esterni (ovvero, unittest), allora sii tu stesso il livello esterno! codice in un blocco try / tranne, cattura SystemExit e chiama os._exit lì, e solo lì! In questo modo puoi chiamare sys.exit
normalmente in qualsiasi parte del codice, lascialo passare al livello più alto, chiudendo con grazia tutti i file ed eseguendo tutte le pulizie, e quindi chiamando os._exit.
Puoi anche scegliere quali uscite sono le "quotazioni di emergenza" quelli. Il codice seguente è un esempio di tale approccio:
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!