Esiste un modo per impedire che un'eccezione SystemExit sollevata da sys.exit () venga catturata?

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

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.

È stato utile?

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!
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top