2013-04-20 3 views
16

Come gestire tutte tranne una eccezione?Gestione di tutte tranne una eccezione

try: 
    something 
except NoChildException: 
    raise NoChildException 
except: 
    pass 
+4

Risposta semplice: no. È davvero una cattiva pratica cogliere tutte le eccezioni, poiché tenderai a catturare quelle che non volevi, oscurando gli errori. C'è solo un piccolo numero di casi legittimi per fare una cosa del genere. –

+2

Sembra che tu abbia risposto alla tua stessa domanda. Diteci perché siete insoddisfatti di ciò che avete. –

+0

@ Robᵩ Non proprio, il suo esempio farà una * nuova * eccezione, non re-raise del vecchio. –

risposta

24

La risposta è di fare semplicemente raise:

try: 
    ... 
except SomeException: 
    raise 
except: 
    ... 

raise senza alcuna espressione dopo lo farà semplice aumento l'ultima eccezione generata (anche se è stato gestito!). E 'più o meno equivalente a:

except SomeException as e: 
    raise e 

Se si pensa che un'altra eccezione potrebbe essere gettato nel blocco catch (ovviamente impossibile in questo caso), è necessario utilizzare il formato di quest'ultima per essere sicuri di ri-sollevare l'eccezione destra.

Tuttavia, come notato nel mio commento:

Risposta semplice: non lo fanno. È davvero una cattiva pratica catturare tutte le eccezioni , dato che tenderai a catturare quelle che non volevi, oscurare gli errori. C'è solo un piccolo numero di casi legittimi per fare una cosa del genere.

Basta prendere gli errori che si pensa possano generare il codice, e sai come gestire e lasciare gli altri. Se succede qualcos'altro, il tuo programma uscirà fuori - che è quello che vuoi, come puoi quindi vedere perché si è verificato e gestirlo correttamente.

+2

+1 per "non farlo" – Aya

+0

sono d'accordo. ma ottengo questo: Fail: il metodo Patient.update ha rilevato un'eccezione di tipo ZeroDivisionError quando non dovrebbe avere. Non dovresti mai usare le clausole 'except' nude nel tuo codice. Acquisisci solo NoChildExceptions. invece di questo: ignorato successo eccezione sollevata di tipo: ZeroDivisionError ignorato successo eccezione sollevata di tipo: NameError ignorato successo eccezione sollevata di tipo: AttributeError ignorato successo eccezione sollevata di tipo: TypeError ignorato successo eccezione sollevata di tipo : ValoreErrore Rilevato con successo sollevato NoChildException Test completato –

+0

@ IvanVulović Quindi quello che vuoi è * solo * prendere 'NoChildException's (che è l'esatto opposto di quello che hai chiesto), quindi basta fare' prova: ... eccetto NoChildException: ... ', non c'è bisogno di niente di speciale. –

2

Offrirei questo come un miglioramento della risposta accettata.

try: 
    dosomestuff() 
except MySpecialException: 
    ttype, value, traceback = sys.exc_info() 
    raise ttype, value, traceback 
except Exception as e: 
    mse = convert_to_myspecialexception_with_local_context(e, context) 
    raise mse 

Questo approccio migliora la risposta accettata mantenendo lo stacktrace originale quando MySpecialException 'colto, in modo che quando il vostro gestore di eccezioni di livello superiore registra l'eccezione si otterrà un traceback che punta al punto in cui è stato gettato l'eccezione originale .

0

Ho trovato un contesto in cui rilevare tutti gli errori tranne uno non è una cosa negativa, vale a dire il test dell'unità.

Se ho un metodo:

def my_method(): 
    try: 
     something() 
    except IOError, e: 
     handle_it() 

allora potrebbe plausibilmente avere una prova di unità che assomiglia:

def test_my_method(): 
    try: 
     my_module.my_method() 
    except IOError, e: 
     print "shouldn't see this error message" 
     assert False 
    except Exception, e: 
     print "some other error message" 
     assert False 
    assert True 

Perché ora avete rilevato che my_method appena gettato un'eccezione imprevista.