2009-05-08 6 views
51

Quali sono le migliori pratiche per la creazione di eccezioni? Ho appena visto questo, e non so se dovrei essere inorridito, o come questo. Ho letto più volte nei libri che le eccezioni non dovrebbero mai contenere una stringa, perché le stringhe stesse possono generare eccezioni. Qualche vera verità a questo?Best practice per le eccezioni Python?

Fondamentalmente dalla mia comprensione degli script è che questo è stato fatto in modo che tutte le librerie Python interne avessero un formato di messaggio di errore comune (qualcosa che è disperatamente necessario) così posso capire perché inserire la stringa del messaggio di errore è una buona idea . (Quasi tutti i metodi generano eccezioni a causa della totale necessità che nulla vada oltre).

Il codice in questione è la seguente:

""" 
Base Exception, Error 
""" 
class Error(Exception): 
    def __init__(self, message): 
     self.message = message 

    def __str__(self): 
     return "[ERROR] %s\n" % str(self.message) 

    def log(self): 
     ret = "%s" % str(self.message) 
     if(hasattr(self, "reason")): 
      return "".join([ret, "\n==> %s" % str(self.reason)]) 
     return ret 

class PCSException(Error): 
    def __init__(self, message, reason = None): 
     self.message = message 
     self.reason = reason 
    def __str__(self): 
     ret = "[PCS_ERROR] %s\n" % str(self.message) 
     if(self.reason != None): 
      ret += "[REASON] %s\n" % str(self.reason) 
     return ret 

Questa è solo la punta di un iceberg, ma qualcuno mi può dare una certa comprensione in ciò che rende questo una pessima idea? O se c'è un processo/stile di codifica eccezionalmente migliore.

+0

Penso che il modo migliore sia avere una gerarchia di eccezioni il più possibile profonda, per dare la massima informazione al programmatore. Raccomando qualcosa come questo ad esempio (dal basso verso l'alto): WrongInputError -> InputError -> GeneralInputError -> NonCriticalError -> Errore -> GeneralError -> BaseError -> WhyIsThisHappeningerror. – drozzy

risposta

28

Ho letto diverse volte in libri che eccezioni dovrebbero mai contenere una stringa , perché le stringhe stessi possono generano eccezioni. Qualcosa di vero a questo?

Cosa?

Si prega di fornire un riferimento o un collegamento a questo. È totalmente falso.

Poiché tutti gli oggetti possono generare eccezioni, nessun oggetto può essere contenuto in un'eccezione da quella logica.

No, il "no string" è semplicemente folle in un contesto Python. Forse lo leggi in un contesto C++.


Modifica

C'era una volta (indietro nei tempi antichi) si potrebbe sollevare un'eccezione Python per nome invece che dalla classe reale.

raise "SomeNameOfAnExceptionClass" 

Questo è male. Ma questo è non inclusa una stringa all'interno di un'eccezione. Questa è la denominazione dell'eccezione con una stringa anziché l'oggetto di classe effettivo. Nel 2.5, questo può ancora funzionare, ma riceve un avviso di deprecazione.

Forse questo è ciò che si legge "Non alzare un'eccezione con un nome di stringa"

+0

Ora che ci penso. La maggior parte di loro erano libri in C++, ma ricordo chiaramente un libro di pitone, dove diceva in grassetto "le eccezioni non dovrebbero mai contenere il messaggio di errore, dovrebbero solo contenere un piccolo identificatore (numero o forse una piccola stringa)" Ricordo il libro, ma vedrò se riesco a scavare. – UberJumper

+5

Forse si stava riferendo al fatto che non si dovrebbe usare una classe Exception per più situazioni eccezionali. Come MyFrameworkException ('File non trovato') e MyFrameworkException ('Connessione al database non disponibile'). –

+0

+1 Avere stringhe nelle eccezioni è molto utile. Altre lingue oltre a Python supportano anche l'aggiunta di informazioni descrittive ai costrutti o alle eccezioni di errore ... possono chiamarlo "contesto" o "ragione" e possono rappresentarlo come una stringa o qualche altro oggetto, ma è sempre lo stesso affare . –

3

La prima impressione è che è tutto troppo codice un'eccezione.

Le eccezioni di formattazione devono essere eseguite nella configurazione del logger. Lo stesso vale per il logging stesso.

Inoltre, ridefinisce l'attributo del messaggio standard (e deprecato) e non chiama il costruttore della superclasse. (Questo potrebbe non rompere il concatenamento di eccezioni Python 3.0, non ho provato perché sto eseguendo 2.6)

La maggior parte di ciò che il codice aggiuntivo può essere realizzato utilizzando BaseException.args, accedendo al seguente come il "messaggio":

'\n==> '.join(exception.args) 

direi che se qualcosa può essere fatto utilizzando un meccanismo comune/idiomatica, dovrebbe in particolare essere fatto in modo di gestione delle eccezioni. (Eccezioni essendo un meccanismo per segnalare qualcosa attraverso strati applicativi.)

Personalmente, cerco di evitare tutto ciò al di là

class SomeException(Exception): pass 

(Esonero di responsabilità:. Rispondere soggettiva, forse per natura della questione)

+0

Il problema principale di un logger è che alcuni degli script sono come 20-30 linee. Per impostazione predefinita, tutti gli output vengono inviati alla console (e deve essere eseguito) – UberJumper

+0

Probabilmente si potrebbe esternalizzare la configurazione della registrazione in un modulo condiviso proprio come sembra esternare la formattazione e gli errori di registrazione nelle loro definizioni. La separazione delle preoccupazioni di solito tende a scontrarsi con le dimensioni del codice assoluto però. – millimoose

+0

Non uso nulla oltre la semplice classe come hai menzionato. Per favore, mi aiuti su questo ** _ Formattazione delle eccezioni dovrebbe essere fatta nella configurazione del logger. ** con un esempio semplice e facile da capire. Grazie –

73

Robust exception handling (in Python) - un post del blog "le migliori pratiche per le eccezioni Python" che ho scritto qualche tempo fa. Potresti trovarlo utile

Alcuni punti chiave del blog:

Mai utilizzare le eccezioni per il controllo di flusso esistono

eccezioni per situazioni eccezionali: gli eventi che non sono una parte di esecuzione normale.

Considerare 'trova' su una stringa restituendo -1 se il modello non viene trovato, ma l'indicizzazione oltre la fine di una stringa genera un'eccezione. Non trovare la stringa è normale esecuzione.

gestire le eccezioni a livello che sa come gestire loro

...

Il miglior posto è quel pezzo di codice che può gestire l'eccezione. Per alcune eccezioni, come errori di programmazione (ad esempio IndexError, TypeError, NameError, ecc.) Sono meglio lasciate al programmatore/utente, perché "gestirle" nasconderà solo bug reali.

Chiedi sempre "è questo il posto giusto per gestire questa eccezione?" e stai attento a catturare tutte le eccezioni.

Documento le eccezioni generate dal codice

...

pensando che eccezioni il codice può buttare vi aiuterà a scrivere meglio, il codice più sicuro e più Encapsulated

+3

È consuetudine fornire un sinossi di link esterni. – dbn

+4

Non sono sicuro di ricordare cosa era consuetudine nel 2009 quando è stata pubblicata questa risposta :-) Sentiti libero di suggerire una modifica –

+1

Tuttavia, il suo articolo vale la pena leggerlo nella sua interezza e dà un contributo prezioso nel rispondere a questa domanda. –

4

Credo che il consiglio contro la creazione di eccezioni con una stringa provenga da "Learning Python" (O'Reilly). In una sezione intitolata Le eccezioni di stringa sono corrette!, indica l'abilità (ora rimossa) di creare un'eccezione direttamente con una stringa arbitraria.

Il codice dà come esempio è:

myexc = "My exception string" 
try: 
    raise myexc 
except myexc: 
    print ('caught') 

Questo è il P858 della Quarta Edizione (Paperback).