Quando si utilizza PyCharm IDE, l'utilizzo di except:
senza un tipo di eccezione attiva un promemoria dall'IDE che questa clausola di eccezione è Too broad
.
Dovrei ignorare questo consiglio? O è Pythonic specificare sempre il tipo di eccezione?
Quando si utilizza PyCharm IDE, l'utilizzo di except:
senza un tipo di eccezione attiva un promemoria dall'IDE che questa clausola di eccezione è Too broad
.
Dovrei ignorare questo consiglio? O è Pythonic specificare sempre il tipo di eccezione?
Risposte:
È quasi sempre meglio specificare un tipo di eccezione esplicita. Se usi una except:
clausola nuda , potresti finire per rilevare eccezioni diverse da quelle che ti aspetti di catturare: questo può nascondere bug o rendere più difficile il debug dei programmi quando non fanno ciò che ti aspetti.
Ad esempio, se stai inserendo una riga in un database, potresti voler rilevare un'eccezione che indica che la riga esiste già, in modo da poter eseguire un aggiornamento.
try:
insert(connection, data)
except:
update(connection, data)
Se si specifica un bare except:
, si rileverà anche un errore di socket che indica che il server del database è caduto. È meglio rilevare solo le eccezioni che sai come gestire: spesso è meglio che il programma fallisca nel punto dell'eccezione piuttosto che continuare ma comportarsi in modi strani e inaspettati.
Un caso in cui potresti voler utilizzare un bare except:
è al livello più alto di un programma che devi sempre essere in esecuzione, come un server di rete. Ma poi, devi stare molto attento a registrare le eccezioni, altrimenti sarà impossibile capire cosa non va. Fondamentalmente, dovrebbe esserci al massimo un solo posto in un programma che fa questo.
Un corollario di tutto ciò è che il tuo codice non dovrebbe mai funzionare raise Exception('some message')
perché impone l'uso del codice client except:
(o except Exception:
che è quasi altrettanto cattivo). È necessario definire un'eccezione specifica per il problema che si desidera segnalare (magari ereditando da una sottoclasse di eccezioni incorporata come ValueError
o TypeError
). Oppure dovresti sollevare una specifica eccezione incorporata. Ciò consente agli utenti del codice di prestare attenzione nel cogliere solo le eccezioni che desiderano gestire.
except:
cattura anche (tra molte altre cose) NameError
e AttributeError
, quindi se sbagli qualcosa nel try
blocco (ad esempio la tua funzione "inserisci" viene effettivamente chiamata insert_one
perché qualcuno non ha valutato la coerenza quanto dovrebbe), cerca sempre di farlo in silenzio update()
.
main()
)?
except Exception:
catturerà NameError
e AttributeError
anche. Ciò che rende nudo except:
così male è che cattura cose che non hanno motivo di essere scoperte , ad esempio SystemExit
(sollevato quando chiami exit
o sys.exit
, e ora hai impedito un'uscita prevista) e KeyboardInterrupt
(di nuovo, se l'utente preme Ctrl-C
, probabilmente non vuoi continuare a correre solo per far loro dispetto). Solo quest'ultimo ha senso da catturare e dovrebbe essere catturato esplicitamente. Almeno except Exception:
lascia che quei due si propagino normalmente.
Non dovresti ignorare il consiglio che ti dà l'interprete.
Dalla Guida allo stile PEP-8 per Python:
Quando si individuano le eccezioni, menzionare eccezioni specifiche ogni volta che è possibile invece di utilizzare una semplice clausola tranne:.
Ad esempio, usa:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
Una semplice clausola tranne: catturerà le eccezioni SystemExit e KeyboardInterrupt, rendendo più difficile interrompere un programma con Control-C e può mascherare altri problemi. Se vuoi catturare tutte le eccezioni che segnalano errori di programma, usa tranne Eccezione: (nudo eccetto equivale a tranne BaseException :).
Una buona regola pratica è limitare l'uso di clausole "tranne" a due casi:
Se il gestore delle eccezioni stamperà o registrerà il traceback; almeno l'utente saprà che si è verificato un errore. Se il codice deve eseguire un po 'di lavoro di pulizia, ma lascia che l'eccezione si propaghi verso l'alto con raise. provare ... finalmente può essere un modo migliore per gestire questo caso.
Non specifico per Python questo.
Il punto centrale delle eccezioni è affrontare il problema il più vicino possibile a dove è stato causato.
Quindi mantieni il codice che potrebbe in circostanze eccezionali potrebbe innescare il problema e la risoluzione "uno accanto all'altro".
Il fatto è che non puoi conoscere tutte le eccezioni che potrebbero essere generate da un pezzo di codice. Tutto quello che puoi sapere è che se si tratta di un'eccezione di file non trovato, potresti intercettarlo e chiedere all'utente di ottenerne uno che esegue o annulla la funzione.
Se metti try catch in giro, non importa quale problema ci fosse nella tua routine di file (sola lettura, permessi, UAC, non proprio un pdf, ecc.), Tutti cadranno nel tuo file not found catch, e il tuo utente sta urlando "ma c'è, questo codice fa schifo"
Ora ci sono un paio di situazioni in cui potresti prendere tutto, ma dovrebbero essere scelte consapevolmente.
Vengono catturati, annullati alcune azioni locali (come la creazione o il blocco di una risorsa (ad esempio l'apertura di un file su disco per la scrittura), quindi si lancia di nuovo l'eccezione, per essere affrontati a un livello superiore)
L'altro è che non ti interessa perché è andato storto. Ad esempio la stampa. Potresti avere un problema a tutto tondo, per dire C'è qualche problema con la tua stampante, per favore risolvilo e non uccidere l'applicazione a causa di ciò. Se il tuo codice eseguisse una serie di attività separate utilizzando una sorta di pianificazione, non vorresti che l'intera cosa muoia, perché una delle attività non è riuscita.
Nota Se si esegue quanto sopra, non posso raccomandare un qualche tipo di registrazione delle eccezioni, ad esempio, prova abbastanza bene il catch log end.
Prenderai anche, ad esempio, Control-C con quello, quindi non farlo a meno che non lo "lanci" di nuovo. Tuttavia, in quel caso dovresti usare piuttosto "finalmente".
Specificare sempre il tipo di eccezione, ci sono molti tipi non si vuole prendere, come SyntaxError
, KeyboardInterrupt
, MemoryError
etc.
except Exception:
eviteremmo i tipi di cui sopra che non vogliamo catturare?
except Exception
è ok.
except Exception
cattura SyntaxError
e MemoryError
perché è la loro classe base. KeyboardInterrupt
, SystemExit
(generato da sys.exit()
) non vengono catturati (sono sottoclassi BaseException immediate)
Ecco i luoghi in cui uso tranne che senza il tipo
Questo è l'uso principale nel mio codice per le eccezioni non controllate
Aggiungo sempre questo, in modo che il codice di produzione non versi stacktrace
Ho due modi per farlo:
Preferisco così, trovo più facile rilevare quali eccezioni avrebbero dovuto essere rilevate in modo appropriato: "vedo" meglio il problema quando un'eccezione di livello inferiore viene registrata da un livello superiore
Alcuni colleghi preferiscono questo modo, poiché mantiene le eccezioni di livello inferiore nelle funzioni di livello inferiore, a cui "appartengono".
Prova questo:
try:
#code
except ValueError:
pass
Ho ricevuto la risposta da questo link, se qualcun altro si imbatte in questo problema , dai un'occhiata