2010-12-12 16 views
19

Quando alzo le mie proprie eccezioni nelle mie librerie Python, lo stack di eccezioni mostra la linea di rilancio stessa come l'ultimo elemento dello stack. Questo ovviamente non è un errore, è concettualmente giusto, ma punta l'attenzione su qualcosa che non è utile per il debug quando stai usando il codice esternamente, ad esempio come modulo.Non mostrare Python raise-line nello stack di eccezioni

C'è un modo per evitarlo e forzare Python a mostrare il precedente all'ultimo elemento dello stack come l'ultimo, come le librerie standard di Python.

+7

La linea di sollevamento è nascosta quando viene sollevata dal codice C compilato (perché non c'è una linea di rilancio da mostrare). Le parti Python delle librerie standard mostreranno ancora l'istruzione raise in un traceback. –

+0

Forse potresti hackerare 'sys.excepthook' per escludere l'ultima riga se si tratta di un' raise'. Ma generalmente non è possibile, ci si abitua. – delnan

+4

Si potrebbe sempre sollevare un'eccezione utile. –

risposta

7

Avviso dovuto: la modifica del comportamento dell'interprete è generalmente disapprovata. E in ogni caso, vedere esattamente dove è stato sollevato un errore può essere utile nel debug, specialmente se una funzione può generare un errore per diversi motivi.

Se si utilizza il modulo traceback e si sostituisce sys.excepthook con una funzione personalizzata, è probabilmente possibile farlo. Ma la modifica influirà sulla visualizzazione degli errori per l'intero programma, non solo sul modulo, quindi probabilmente non è raccomandato.

Si potrebbe anche cercare di inserire il codice in try/except blocks, quindi modificare l'errore e rilanciarlo. Ma probabilmente è meglio spendere i propri errori rendendo improbabili errori imprevisti e scrivere messaggi di errore informativi per quelli che potrebbero sorgere.

-1

Suggerisco di non utilizzare il meccanismo Exception per convalidare gli argomenti, per quanto allettanti sia. Codificare con le eccezioni come condizionali è come dire "crash la mia app se, come sviluppatore, non penso a tutte le cattive condizioni che i miei argomenti forniti possono causare. Forse usando eccezioni per cose non solo fuori dal tuo controllo ma anche quali sono sotto controllo di qualcos'altro come il sistema operativo o l'hardware o il linguaggio Python sarebbe più logico, non lo so.In pratica comunque utilizzo eccezioni quando richiedi una soluzione.

Per rispondere alla tua domanda, in parte, è altrettanto semplice per codificare questa convenzione:

class MyObject(object): 
    def saveas(self, filename): 
     if not validate_filename(filename): 
      return False 
     ... 

chiamante

if not myobject.saveas(filename): report_and_retry() 

Forse non è una grande risposta, solo una cosa a cui pensare.

+0

Ho dovuto revocarlo perché sto evitando il maggior numero possibile di eccezioni e sto solo dicendo al mio programma di affrontarlo, scavalcarlo, registrare il problema e continuare a camminare. Ho avuto più debug di successo qui che con le eccezioni lanciate ovunque come tutti gli altri ... in pratica sto usando print() invece di aumentare – Tcll

+0

Ho appena pensato anche all'altro lato di questo, e probabilmente il motivo la maggior parte farebbe un downvote su questo (non lo farò comunque, dato che il mio ultimo commento è ancora valido), la maggior parte dei buoni sviluppatori non getta eccezioni per nulla in caso di utilizzo errato, ma solo casi particolari che meritano un'eccezione ... concesso quanto sopra può ancora succedere in casi particolari che nemmeno il tuo codice potrebbe catturare. ad esempio: filename è un oggetto che rappresenta una str. – Tcll

4

è possibile creare il proprio hook di eccezione in python. di seguito è riportato l'esempio del codice che sto usando.

import sys 
import traceback 

def exceptionHandler(got_exception_type, got_exception, got_traceback): 
    listing = traceback.format_exception(got_exception_type, got_exception, got_traceback) 
    # Removing the listing of statement raise (raise line). 
    del listing[-2] 
    filelist = ["org.python.pydev"] # avoiding the debuger modules. 
    listing = [ item for item in listing if len([f for f in filelist if f in item]) == 0 ] 
    files = [line for line in listing if line.startswith(" File")] 
    if len(files) == 1: 
     # only one file, remove the header. 
     del listing[0] 
    print>>sys.stderr, "".join(listing) 

E di seguito sono alcune linee che ho utilizzato nel mio codice di eccezione personalizzato.

sys.excepthook = exceptionHandler 
raise Exception("My Custom error message.") 

Nel eccezione metodo è possibile aggiungere i nomi dei file o nomi dei moduli nella lista "nomi di file", se si desidera ignorare tutti i file indesiderati. Come ho ignorato il modulo Python pydev dal momento che sto usando pydev debugger in Eclipse.

Quanto sopra viene utilizzato nel mio modulo per uno scopo specifico. puoi modificarlo e usarlo per i tuoi moduli.