2013-07-16 4 views
5

Mi piacerebbe sapere come è il modo standard (se ce n'è uno) per ottenere le eccezioni che un modulo/funzione può generare.Come trovare le eccezioni che possono essere generate per un particolare modulo in Python?

Prendiamo ad esempio json. Naturalmente sono andato allo Documentation ma non ho trovato un modo standard per sapere quali eccezioni possono essere sollevate in certe funzioni (come dump o load). Non è chiaro per me (a prima vista) se solo la cattura di TypeError sarà sufficiente.

Quali sono le raccomandazioni per essere sicuri che stiamo prendendo tutto (e solo abbastanza) su un particolare modulo/funzione?

+0

Nota: anche la documentazione menziona 'ValueError'. – torek

risposta

3

Non sono mai stato completamente soddisfatto delle eccezioni di Python. Funziona bene nella pratica, è la teoria che mi dà fastidio. :-) In particolare, perché tutto è dinamico, anche se sai che evil() solleva solo ZorgError e chiama spam() che solleva EggsError, in modo che al massimo tu riceva quei due errori da una chiamata a evil(), qualcuno potrebbe aggiustare le cose dietro la tua schiena e cambia questo.

Detto questo, alcuni documenti sono migliori di altri. Ad esempio os.kill può ovviamente aumentare OSError se lo kill fallisce e TypeError se lo si chiama con qualcosa di diverso da due numeri interi, ma lo sapevate che può anche aumentare OverflowError?

>>> os.kill(9999999999999, 0) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
OverflowError: signed integer is greater than maximum 

Se si sta tentando di scrivere ragionevolmente codice a prova di proiettile che fa le cose come leggere un pid file e sonda per vedere se un processo è in esecuzione, si scopre che devi prendere questo OverflowError nel caso in cui il pid nel file pid è un numero intero, ma è fuori portata. Sarebbe bello se questo fosse nella documentazione (l'ho trovato con la tortura-test, invece.)

Semplicemente la cattura di tutto (except: o except Exception) è di solito non è adatto come di solito prende troppa (tra cui, ad esempio, RuntimeError da uno stack overflow). Quindi, come fai a sapere cosa catturare? Penso che potrebbe essere bello se le funzioni foglia nelle librerie standard avessero un attributo "eccezioni che alzo direttamente" o un requisito di documentazione, ma semplicemente non c'è.


Edit: ho notato in un commento di cui sopra che la documentazione JSON menziona esplicitamente ValueError. Non esplicitamente richiamato, ma trovato negli autotest di JSON, sono UnicodeDecodeError (che è ovvio una volta che ci pensi) e AttributeError (non così ovvio). La documentazione menziona anche che è possibile ottenere uno OverflowError.Naturalmente, se si utilizza json.dump, che accetta uno stream su cui scrivere, è possibile ottenere anche tutti gli errori del flusso. Questo è il motivo per cui un "elenco di eccezioni zorg() si alza direttamente" non è sempre molto utile.

+0

Apprezzo la tua risposta. È abbastanza chiaro come si possa perdere l'occasione di cogliere qualche eccezione. Con questo in mente, qual è il comune approccio Pythonic? Se si tratta di una funzione come questa, 'os.kill' cattura qualunque cosa la documentazione indichi e lasci i casi d'angolo? E per i moduli non ben documentati come 'json', prendi semplicemente 'Exception'? –

+0

Non sono sicuro di "comune Pythonic". Ci sono più problemi da considerare. A volte il punto in cui si verifica un errore è di livello relativamente alto, quindi è sufficiente lasciare che le routine di basso livello falliscano e passare l'errore in poi. A volte il luogo in cui si verifica un errore è giusto quando si verifica. A volte l'oggetto non è "catturare l'errore", ma piuttosto pulire (ad esempio, sbloccare una struttura dati), nel qual caso si desidera un blocco 'try' con un contesto di stile' finally', o 'with' manager. Tuttavia, ho trovato un consenso generale sul fatto che 'tranne Exception' sia raramente corretto. – torek

2

Ebbene si può utilizzare il tipo globale Exception-catch il Exceptions:

try: 
    1 + "2" 
except Exception as error: 
    print "Error", error 

L'output sarà qualcosa di simile:

Error unsupported operand type(s) for +: 'int' and 'str' 

Se volete sapere il nome di tale eccezione si può fare qualcosa come:

try: 
    1 + "2" 
except Exception as error: 
    print error.__class__.__name__, error 

e th L'output sarà qualcosa del tipo:

TypeError unsupported operand type(s) for +: 'int' and 'str' 
+0

Grazie per aver pubblicato un modo pratico per ottenere i nomi delle eccezioni. Il problema principale è che non ho il 'code' in avanzato per sapere quali eccezioni possono essere sollevate. Ho solo pensato di poter trovare un modo per avere una documentazione esauriente sulle eccezioni su un particolare modulo. –

+0

Prego, penso che in questo modo sia utile rilevare "Eccezioni" perché a volte il doc di un modulo non funziona o talvolta non si conosce il tipo di "Eccezione" che una libreria può sollevare. –