2012-04-25 15 views
9

Domanda di base: Qual è il modo più pitonico/logico per creare classi di avvertenza personalizzate? Quali sono le classi di avviso e di eccezione corrette che dovrei creare in sottoclassi?Pythonico, avvisi personalizzati

Motivazione: I requisiti per la libreria che sto scrivendo specificare che se un oggetto cMyContainer contiene un elemento x e il chiamante della biblioteca cerca di mettere un "duplicato" di x - lo chiamano y - in c, viene inviato un avviso al chiamante e il valore restituito di c.my_transformation_method(x, y) viene inserito in c per sostituire x. In altre parole, MyContainer sostituirà gli elementi con i loro duplicati, ma deve avvisare l'utente quando lo fa.

Sulla base della mia lettura, il modo più flessibile per avvisare il chiamante di una libreria su un'azione non fatale è con lo warnings standard module. Permette al chiamante di gestire l'avvertimento come meglio crede, facendo qualsiasi cosa, ignorando gli avvertimenti e considerandoli come errori. (Si noti che sto usando Python 3, ma io non credo che sia essenziale per la domanda qui.)

Esempio: Quello che ho fatto è definito il seguente sottoclasse avvertimento:

class DuplicateItemWarning(UserWarning, ValueError): 
    pass 

Quindi il metodo add() di MyContainer chiama warnings.warn('detected duplicate', DuplicateItemWarning) quando rileva un tentativo di inserimento di un elemento duplicato.

Domande specifiche:

  1. Dovrei essere sottoclasse UserWarning come sopra, o semplicemente sublcassing Warning?

  2. Sembra semanticamente sensato sottoclasse ValueError (che, nell'esempio di cui sopra, semplicemente inserisce ValueError nel MRO tra il Warning e Exception) nel caso in cui un chiamante vuole trattare gli avvisi come errori. C'è uno svantaggio di ciò che non vedo?

  3. Impossibile trovare domande precedenti su StackOverflow sulla personalizzazione delle classi di avviso. Questo perché i programmatori Python non amano nemmeno usare il modulo warnings?

+0

IMO, l'approccio più poderoso è quello di utilizzare solo gli avvisi e le eccezioni incorporati, fornendo il proprio messaggio. Qual è il caso della sottoclasse? – Wilduck

+0

@Wilduck Potrei aver bisogno di creare altri tipi di avvertimenti per questa libreria, ma mi piace anche la semantica di avere un avviso che è anche un 'errore di valore'. In ogni caso, qual è l'avviso predefinito corretto da utilizzare per questa situazione? 'Warning'? 'UserWarning'? – wkschwartz

+0

Penso che non sia certamente 'Warning'. È la classe base di tutti gli avvertimenti. Vedi http://docs.python.org/py3k/library/warnings.html#warning-categories per un elenco completo, dipende da cosa dovrebbe significare il tuo avvertimento – jadkik94

risposta

4

Dopo aver letto il PEP 230 sul quadro di avvertimento e le avvertenze documentazione, penso di avere la risposta alle tue domande:

  1. UserWarning e tutti gli altri stanno avvertendo le categorie, non sembrano avere un altro ruolo oltre alla semplice classificazione. In questo modo è possibile filtrarli nell'ambiente di produzione, ad esempio. Quindi, in pratica, è possibile creare una sottoclasse da Warning se l'avviso non ricade in nessun'altra categoria. Se nel contesto, UserWarning o RuntimeWarning sembrano abbastanza, basta usarli.

  2. Warning s sono già Exception s.Quindi, tecnicamente, per "catturarli" come errori, devi solo cambiare il filtro, senza bisogno di sottoclasse da qualsiasi XXXError. Ora, di nuovo, tutto ha senso. Se gli avvertimenti riguardano i valori trasmessi, è possibile creare una sottoclasse da ValueError, in particolare se ci sarebbero molti avvisi personalizzati diversi, ci si aspetterebbe che il chiamante "catturi" tutti gli avvisi relativi ai valori tutti in una volta.

    try: 
        # do something 
    except MyCustomWarningOne: 
        # do something else 
    except MyCustomWarningTwo: 
        # do something else also 
    except ValueError: # or RuntimeWarning if you subclass from it 
        # catch some other warning (both of these subclass from ValueError for example) 
    
  3. Il modulo warnings è l'idea di Guido van Rossum. (Vedi PEP 230). Se questo non è abbastanza Pythonic ...: D

+1

Quindi, se ho capito bene, il mio approccio alla sottoclassi è buono finchè questo rende i miei avvertimenti più intuitivi per gli utenti. Evitando la sottoclasse, _i.e._, usando direttamente 'RuntimeWarning' (' UserWarning' sembra una vera fuoriuscita dal momento che il suo nome è così non specifico) va bene quando la mia libreria non ha molti avvertimenti da dare. È giusto? – wkschwartz

+0

Sì, questo è ciò che intendo. Penso che abbia senso farlo, ma non posso garantire che sia il modo in cui dovresti farlo. Vedi anche altre opinioni :) – jadkik94

+0

Usare 'Warning' come classe base e il menzionato * filtering * significa che puoi facilmente catturare + report + ignorare tutti gli avvertimenti nella clausola' except Warning as warn: '- compresi quelli che hai fatto non inventato. – pepr