Perché sollevare un'eccezione se Python lo solleva?

3

Ho un responsabile globale delle posizioni delle schermate, quindi gli articoli non devono memorizzare le loro posizioni.

class Screen_Position_Keeper:

    # functions to add stuff

    def get_px_row( self, item ):
        try:
            return self.item_to_row[ item ]
        except KeyError:
            raise KeyError( 'You never registered that item' )

Perché non fare solo quanto segue?

class Screen_Position_Keeper:

    # functions to add stuff

    def get_px_row( self, item ):
        return self.item_to_row[ item ]
    
posta user2738698 26.09.2016 - 00:28
fonte

4 risposte

6

La risposta alla tua domanda è che vuoi eccezioni significative.

Nella maggior parte dei contesti, ciò comporta un'eccezione che aggiunge informazioni utilizzabili in due modi:

  • Utile digitazione allo sviluppatore che potrebbe rilevare l'eccezione
  • Informazioni utili sull'errore all'utente (e / o allo sviluppatore che può tradurre l'utente)

Nel tuo esempio, non stai aggiungendo nulla alla normale eccezione. Catturare e quindi reraising efficacemente l'eccezione non è utile. potresti registrare queste informazioni, nel qual caso ora hai aggiunto un valore all'eccezione, ma altrimenti è inutile.

Immagina questo scenario:

try:
   my_web_function()
except my_custom_web_exception:
   do_something_with_this_exception()

È del tutto ragionevole immaginare questo scenario. Potresti fare una richiesta http. La maggior parte delle librerie ha definito i tipi di eccezioni, quindi è possibile rilevare tali eccezioni e, in caso affermativo, fare qualcosa.

Il "qualcosa" dipende dall'applicazione specifica. In un'eccezione http, forse è solo riprovare la richiesta. Ecc.

Ma il punto sta rilevando l'eccezione aggiunge valore e informazioni ed è perseguibile.

    
risposta data 26.09.2016 - 04:12
fonte
3

Un errore che ho riscontrato la scorsa settimana non era dovuto a uno script python, ma vale lo stesso principio. Ho avuto il "privilegio" di dover usare una vecchia versione di sovversione su un progetto. Ho erroneamente digitato in modo errato

prompt: svn co https://some.site.com/some/path

La risposta del sistema era

svn: OPTIONS of 'https://some.site.com/some/path': 200 OK (https://some.site.com)

Questo messaggio non era solo inutile, era scorretto. (Assegnare a qualcuno uno stato "200 OK" HTTP / HTTPS quando ciò che è accaduto era tutt'altro che corretto non è OK.) Inoltre, ci sono più percorsi nella sovversione 1.9 che provocano quell'errore di errore "200 OK" errato. Un messaggio molto più utile sarebbe stato di dirmi che avevo digitato male l'URL del repository.

Strettamente parlando, questo non era un bug in sovversione. Era solo un messaggio di errore mal scritto. Dopotutto, la sovversione ha rilevato e segnalato correttamente il problema. Dal punto di vista dell'utente, si trattava di un grosso bug che era stato risolto per la maggior parte nel 2010. Fortunatamente, una rapida ricerca su google ha prodotto più accessi su stackoverflow.com.

Spesso ai programmatori viene insegnato che dovrebbero semplicemente passare un'eccezione se non possono fare qualcosa al riguardo. Gli istruttori e gli studenti pensano che "fare qualcosa" significhi correggere il problema. In molti casi, non c'è nulla che possa essere fatto per correggere un problema. Questa è una visione troppo ristretta del "fare qualcosa". Aggiunta di un contesto che consente a un utente di affinare il problema e quindi correggerlo è "fare qualcosa".

Un altro modo di considerare le eccezioni a basso livello è che è un'astrazione che perde.

    
risposta data 26.09.2016 - 06:31
fonte
2

In Python, dovresti assolutamente catturare e rilanciare quell'eccezione, per la sola ragione che un lettore del codice vede immediatamente che potrebbe sorgere durante la normale esecuzione.

Questo dice al lettore che viene restituito il valore corrispondente, ma non hai pensato al comportamento corretto quando la chiave non è stata trovata:

def get(key):
  return items[key]

Questo mi dice che ti aspetti di ricevere le chiavi mancanti e che i chiamanti potrebbero ricevere un KeyError. Ci si aspetta che un chiamante prenda questo errore:

def get(key):
  try:
    return items[key]
  except KeyError:
    raise

Questo mi dice che la chiave deve essere presente, qualsiasi altra cosa sarebbe un errore di programmazione:

def get(key):
  assert key in items
  return items[key]

Se crei un messaggio di errore personalizzato, assicurati che questo messaggio contenga tutte le informazioni necessarie per risolvere e comprendere il problema. In particolare, il messaggio di errore dovrebbe contenere la chiave mancante - utilizzare repr() non str() per questo.

"item {!r} was not registered".format(key)

Se la formattazione del messaggio di errore è costosa e il messaggio di errore viene letto raramente perché verrà rilevato nella maggior parte dei casi, è possibile creare un'eccezione personalizzata per rinviare la formattazione finché non viene visualizzato l'errore. È comunque possibile ereditare da KeyError in modo che possa essere catturato senza modifiche:

class NotRegisteredError(KeyError):
  def __init__(self, key):
    super().__init__(key)
    self.key = key

  def __str__(self):
    return "item {!r} was not registered".format(self.key)
    
risposta data 26.09.2016 - 08:33
fonte
-1

Non si dovrebbero gestire eccezioni nel livello logico core. È responsabilità del livello di visualizzazione gestirlo e migliorare la leggibilità del messaggio. Se il codice fornito fa parte del livello logico principale, non eseguire qui la gestione delle eccezioni, ma delegarlo al livello di visualizzazione della chiamata.

    
risposta data 26.09.2016 - 06:30
fonte

Leggi altre domande sui tag