2015-10-20 14 views
25

Qual è il modo migliore per ottenere i messaggi delle eccezioni dai componenti della libreria standard in Python?Come ottenere correttamente il messaggio di eccezione in Python

ho notato che in alcuni casi si può ottenere tramite message campo come questo:

try: 
    pass 
except Exception as ex: 
    print(ex.message) 

ma in alcuni casi (ad esempio, in caso di errori di socket) si deve fare qualcosa di simile:

try: 
    pass 
except socket.error as ex: 
    print(ex) 

Mi chiedevo ci fosse un modo standard per coprire la maggior parte di queste situazioni?

+1

Stai confondendo due cose diverse - 'eccetto Foo as bar:' è lo stesso di 'tranne Foo, bar:' (eccetto il primo è più recente, e continuerà a funzionare in 3.x), sia che l'errore venga fornito con un attributo 'message' o non è separato. – jonrsharpe

+0

@jonrsharpe Modificato – FrozenHeart

+0

@FrozenHeart Stai chiedendo se l'accesso a '.message' per un errore è standard o no? –

risposta

23

Se si guarda il numero documentation for the built-in errors, si noterà che la maggior parte delle classi Exception assegna il primo argomento come attributo message. Non tutti però lo fanno.

particolare, EnvironmentError (con sottoclassi IOError e OSError) ha un primo parametro di errno, secondo di strerror. Non c'è message ... strerror è approssimativamente analogo a quello che normalmente sarebbe un message.

Più in generale, le sottoclassi di Exception possono fare tutto ciò che vogliono. Possono o non possono avere un attributo message. Il futuro built-in Exception s potrebbe non avere un attributo message. Qualsiasi sottoclasse Exception importata da librerie di terze parti o codice utente potrebbe non avere un attributo message.

Penso che il modo corretto di gestirlo sia identificare le sottoclassi specifiche di Exception che si desidera catturare, quindi catturare solo quelle invece di tutto con un except Exception, quindi utilizzare qualsiasi attributo definito da tale sottoclasse.

Se si deve print qualcosa, penso che la stampa della stessa catturato Exception è più probabile che a fare ciò che si vuole, se ha un attributo message o meno.

Si potrebbe anche verificare per l'attributo messaggio se si voleva, in questo modo, ma non sarebbe davvero suggerire come sembra solo disordinato:

try: 
    pass 
except Exception as e: 
    # Just print(e) is cleaner and more likely what you want, 
    # but if you insist on printing message specifically whenever possible... 
    if hasattr(e, 'message'): 
     print(e.message) 
    else: 
     print(e) 
+0

Grazie per la risposta. C'è qualche ragione particolare per usare 'str (ex)' invece di solo 'ex'? – FrozenHeart

+2

@FrozenHeart - 'print()' chiama automaticamente 'str()' per te. Non c'è alcun motivo per chiamarlo manualmente, anche se è innocuo dal momento che chiamare 'str()' su una stringa restituirà semplicemente la stringa stessa. – ArtOfWarfare

+1

@ArtOfWarfare Penso che potrebbero esserci problemi con 'str()' se il messaggio è di tipo 'unicode'. – kratenko

0

di migliorare la risposta fornita da @artofwarfare, qui è quello che considero un modo più ordinato per verificare l'attributo message e stamparlo o stampare l'oggetto Exception come fallback.

try: 
    pass 
except Exception as e: 
    print getattr(e, 'message', repr(e)) 

La chiamata a repr è facoltativo, ma ritengo necessario, in alcuni casi d'uso.


Update # 1:

A seguito del commento di @MadPhysicist, ecco una prova del motivo per cui potrebbe essere necessario la chiamata a repr.Provare a eseguire il seguente codice nel tuo interprete:

try: 
    raise Exception 
except Exception as e: 
    print(getattr(e, 'message', repr(e))) 
    print(getattr(e, 'message', str(e))) 

Aggiornamento # 2:

Ecco una demo con le specifiche per Python 2.7 e 3.5: https://gist.github.com/takwas/3b7a6edddef783f2abddffda1439f533

+1

'getattr' genera un'eccezione se l'oggetto passato non ha l'attributo richiesto. Se volessi fare qualcosa del genere, penso che dovresti usare il terzo argomento opzionale per 'getattr', come questo:' print getattr (e, 'message', e) '. Debatably meglio di quello che ho fatto. Un'altra opzione sarebbe 'print (e.message if hasattr (e, 'message') else e)'. – ArtOfWarfare

+0

@ArtOfWarfare: È interessante notare che l'avevo appena scoperto e che stavo aggiornando questa risposta. Funziona bene in Python 2. Il problema che si pone è con Python 3. –

+0

Sono su Python 2.7.13. Il primo metodo non ha funzionato. – ArtOfWarfare