Informazioni sulla cattura di QUALSIASI eccezione


696

Come posso scrivere un blocco try/ exceptche rileva tutte le eccezioni?


4
Nella maggior parte dei casi, probabilmente stai sbagliando qualcosa se stai cercando di cogliere qualche eccezione. Voglio dire, puoi semplicemente sbagliare a scrivere qualcosa nel tuo codice e non lo saprai nemmeno. È buona norma individuare eccezioni specifiche.
vwvolodya,

12
Per essere più precisi, catturare tutte le possibili eccezioni è un problema solo se vengono catturati silenziosamente. È difficile pensare a dove questo approccio sia appropriato, oltre a dove vengono stampati sys.stderre possibilmente registrati i messaggi di errore rilevati. Questa è un'eccezione perfettamente valida e comune.
Evgeni Sergeev

hai provato try: whatever() except Exception as e: exp_capture() :?
Charlie Parker

Risposte:


564

Puoi ma probabilmente non dovresti:

try:
    do_something()
except:
    print "Caught it!"

Tuttavia, questo catturerà anche eccezioni come KeyboardInterrupte di solito non lo vuoi, vero? A meno che non si sollevi nuovamente l'eccezione, vedere il seguente esempio dai documenti :

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise


15
La tua ultima affermazione non è vera, devi dire esplicitamente except Exception:il nudo tranne che hai lì catturerà anche quelli di BaseException.
Pykler,

7
Dovresti davvero stampare su stderr.
nyuszika7h,

41
Non sono molto d'accordo con l'affermazione "non dovrei". Dovresti farlo con parsimonia. Ci sono momenti in cui hai a che fare con librerie di terze parti (a volte caricate in modo dinamico !!) che sono diventate totalmente pazze di eccezioni e rintracciarle tutte può essere un compito molto doloroso, e se ne perdi solo una, ne hai davvero una enorme bug doloroso nel tuo sistema. Detto questo, è bene rintracciarne il maggior numero possibile e gestirli in modo appropriato e quindi avere un backup tutto per quelli che ti mancano.
Blaze,

26
Ciò che trovo anche strano è che in un linguaggio di battitura a papera in cui non dichiari le variabili di istanza, improvvisamente è molto preoccupato di non digitare tutte le tue eccezioni. Hmm!
Blaze,

834

A parte una except:clausola semplice (che come altri hanno detto che non dovresti usare), puoi semplicemente catturare Exception:

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

Normalmente potresti considerare di farlo solo al livello più esterno del tuo codice se, ad esempio, volessi gestire eventuali eccezioni altrimenti non rilevate prima di terminare.

Il vantaggio di except Exceptionover the bare exceptè che ci sono alcune eccezioni che non catturerà, molto ovviamente KeyboardInterrupte SystemExit: se le prendessi e le ingoiassi, potresti rendere difficile a chiunque uscire dalla tua sceneggiatura.


Avevo la stessa cosa nella mia mente, ma il loro è uno svantaggio, supponiamo che siano due errori quando viene catturato una volta e e tranne che stai solo stampando uscirai dal blocco try e non conoscerai mai il secondo errore .. .

6
Per chiunque si stia chiedendo, totalmente contrario alle mie aspettative, questo catturerà comunque cose di sottoclasse senza eccezioni come ints, almeno in Python 2.x.
Joseph Garvin,

5
@JosephGarvin, non è corretto, cioè questo non catturerà "non eccezioni" che non rientrano nella sottoclasse Exception. Si noti che è impossibile sollevare intun'eccezione e tentare di farlo genera TypeErrorun'eccezione, che è ciò che verrebbe catturato dalla except Exceptionclausola allegata in tal caso. D'altra parte, una classe vecchio stile può essere sollevata e si qualifica come una "non eccezione" che non va in sottoclasse Exception- questo sarà colto da una exceptclausola nuda ma non da una except Exceptionclausola.
Yoel

4
@JosephGarvin controlla questo post sul blog: chris-lamb.co.uk/posts/no-one-expects-string-literal-exception Sono con @Yoel su questo, i tuoi test hanno appena mascherato ilTypeError
Duncan

2
@CharlieParker non c'è niente di male nel catturarli se è quello che vuoi ma per lo più non lo fai. La chiamata di sys.exit()solito significa che ti aspetti che l'app venga chiusa, ma se ricevi SystemExit non lo farà. Allo stesso modo se si preme control-C su uno script in esecuzione (Ctrl-break su Windows) ci si aspetta che il programma si fermi, non per catturare l'errore e andare avanti. Ma puoi prendere uno di questi / entrambi se vuoi fare la pulizia prima di esistere.
Duncan

100

Puoi farlo per gestire le eccezioni generali

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message

8
Questo potrebbe non catturare tutte le eccezioni, poiché la classe di base per tutte le eccezioni è BaseException e ho riscontrato un codice di produzione che non appartiene alla famiglia delle classi di eccezioni. Vedi docs.python.org/3/library/… per dettagli al riguardo.
DD

4
Questo non cattura tutte le eccezioni.
Andy_A̷n̷d̷y̷,

6
Tecnicamente, dovrebbe cogliere tutte le eccezioni non uscenti dal sistema. Dai documenti @DDay collegati: " eccezione BaseException: la classe base per tutte le eccezioni integrate. Non si intende che sia ereditata direttamente dalle classi definite dall'utente (per questo, usa l'eccezione)." A meno che tu non stia lavorando con un codice che lo ignora o non hai bisogno di catturare le eccezioni che escono dal sistema, quanto sopra dovrebbe essere ok da usare.
Peter Cassetta,

@PeterCassetta quando vorresti catturare il sistema uscendo dalle eccezioni? Sembra il filo conduttore nella domanda che non vogliamo coglierli, ma non capisco perché. Perché non di solito?
Charlie Parker,

68

Per catturare tutte le possibili eccezioni, cattura BaseException. È in cima alla gerarchia delle eccezioni:

Python 3: https://docs.python.org/3.5/library/exceptions.html#exception-hierarchy

Python 2.7: https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

Ma come menzionato da altre persone, di solito non avresti bisogno di questo, solo per casi specifici.


1
Desiderare salvare l'avanzamento di un lavoro di lunga durata dopo aver premuto Ctrl-C è insolito?
BallpointBen,

54

Esempio molto semplice, simile a quello trovato qui:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

Se stai tentando di rilevare TUTTE le eccezioni, inserisci tutto il codice nell'istruzione "try:", al posto di "print" Eseguendo un'azione che potrebbe generare un'eccezione. "'.

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

Nell'esempio sopra, vedresti l'output in questo ordine:

1) Esecuzione di un'azione che può generare un'eccezione.

2) Infine viene chiamato direttamente dopo aver eseguito l'istruzione try se viene generata o meno un'eccezione.

3) "È stata generata un'eccezione!" o "Tutto sembra fantastico!" a seconda che sia stata generata un'eccezione.

Spero che sia di aiuto!


26

Esistono diversi modi per farlo, in particolare con Python 3.0 e versioni successive

Approccio 1

Questo è un approccio semplice ma non raccomandato perché non sapresti esattamente quale riga di codice sta effettivamente generando l'eccezione:

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

Approccio 2

Questo approccio è consigliato perché fornisce maggiori dettagli su ciascuna eccezione. Include:

  • Numero di riga per il tuo codice
  • Nome del file
  • L'errore reale in modo più dettagliato

L'unico inconveniente è che il tracback deve essere importato.

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()

21

Ho appena scoperto questo piccolo trucco per verificare se i nomi delle eccezioni in Python 2.7. A volte ho gestito eccezioni specifiche nel codice, quindi avevo bisogno di un test per vedere se quel nome si trova in un elenco di eccezioni gestite.

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception

2
try:
    whatever()
except:
    # this will catch any exception or error

Vale la pena ricordare che questa non è una corretta codifica Python. Ciò colpirà anche molti errori che potresti non voler rilevare.


basta usare tranne che non memorizzare nella cache tutte le eccezioni come menzionato in alcune altre risposte. Devi usare BaseException per questo scopo, ma come hai detto, nessuno dovrebbe catturare tutte le eccezioni come questa. Immagino sia giusto iniziare se l'obiettivo è quello di aggiungere più granularità tranne durante lo sviluppo, ma non penso che sarà ...
Pyglouthon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.