Domanda

Ho ricevuto un avviso che BaseException.message è deprecato in Python 2.6 quando uso la seguente eccezione definita dall'utente:

class MyException(Exception):

    def __init__(self, message):
        self.message = message

    def __str__(self):
        return repr(self.message)

E 'il monito:

DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
self.message = message

Cosa c'è di sbagliato in questo? Che cosa devo cambiare per sbarazzarsi di avvertimento deprecazione?

È stato utile?

Soluzione

Solution - quasi nessun codice necessario

Basta ereditare la classe eccezione dalla Exception e passare il messaggio come primo parametro al costruttore

Esempio:

class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    print my # outputs 'my detailed description'

È possibile utilizzare str(my) o (meno elegante) my.args[0] per accedere al messaggio personalizzato.

Sfondo

Nelle versioni più recenti di Python (da 2,6) che siamo tenuti a ereditare le nostre classi di eccezioni personalizzate da Exception che ( a partire da Python 2.5 ) eredita da BaseException. Lo sfondo è descritto in dettaglio nella PEP 352 .

class BaseException(object):

    """Superclass representing the base of the exception hierarchy.
    Provides an 'args' attribute that contains all arguments passed
    to the constructor.  Suggested practice, though, is that only a
    single string argument be passed to the constructor."""

__str__ e __repr__ sono già implementati in modo significativo, in particolare per il caso di un solo arg (che può essere utilizzato come un messaggio).

Non è necessario ripetere realizzazione __str__ o __init__ o creare _get_message come suggerito da altri.

Altri suggerimenti

Sì, è deprecato in Python 2.6 perché sta andando via in Python 3.0

class BaseException non fornisce un modo per memorizzare più il messaggio di errore. Dovrai implementare da soli. È possibile farlo con una sottoclasse che utilizza una proprietà per la memorizzazione del messaggio.

class MyException(Exception):
    def _get_message(self): 
        return self._message
    def _set_message(self, message): 
        self._message = message
    message = property(_get_message, _set_message)

Spero che questo aiuti

class MyException(Exception):

    def __str__(self):
        return repr(self.args[0])

e = MyException('asdf')
print e

Questa è la classe in stile python2.6. La nuova eccezione prende un numero arbitrario di argomenti.

Come per replicare l'avviso

Vorrei chiarire il problema, come non si può replicare questo con codice di esempio del problema, questo replicherà l'avviso in Python 2.6 e 2.7, se si dispone di avvertimenti accesi (tramite il -W bandiera , il PYTHONWARNINGS variabile d'ambiente, oppure il modulo avvertimenti ):

>>> error = Exception('foobarbaz')
>>> error.message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foobarbaz'

Smettere di usare .message

Io preferisco repr(error), che restituisce una stringa che contiene il nome del tipo di errore, il repr del messaggio, se ce n'è uno, e l'repr dei restanti argomenti.

>>> repr(error)
"Exception('foobarbaz',)"

Eliminare l'avviso pur utilizzando .message

E il modo in cui si ottiene eliminare del DeprecationWarning è quello di sottoclasse un'eccezione incorporato come i progettisti Python destinati:

class MyException(Exception):

    def __init__(self, message, *args):
        self.message = message
        # delegate the rest of initialization to parent
        super(MyException, self).__init__(message, *args)

>>> myexception = MyException('my message')
>>> myexception.message
'my message'
>>> str(myexception)
'my message'
>>> repr(myexception)
"MyException('my message',)"

ottenere solo l'attributo .message senza error.message

Se si conosce ci fosse un argomento, un messaggio, per l'eccezione e questo è ciò che si vuole, è preferibile evitare l'attributo messaggio e basta prendere la str dell'errore. Diciamo per un Exception sottoclasse:

class MyException(Exception):
    '''demo straight subclass'''

e di utilizzo:

>>> myexception = MyException('my message')
>>> str(myexception)
'my message'

Si veda anche questa risposta:

modo corretto di dichiarare eccezioni personalizzate in Python moderno?

Per quanto posso dire, semplicemente utilizzando un nome diverso per l'attributo messaggio evita il conflitto con la classe base, e quindi si ferma l'avvertimento deprecazione:

class MyException(Exception):

def __init__(self, message):
    self.msg = message

def __str__(self):
    return repr(self.msg)

Sembra un trucco per me.

Forse qualcuno può spiegare perché l'avvertimento viene emesso anche quando la sottoclasse definisce attributo un messaggio esplicito. Se la classe base non ha più questo attributo, non ci dovrebbe essere un problema.

Proseguendo da di geekQ risposta , la sostituzione del codice preferito dipende da ciò che dovete fare:

### Problem
class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    ### Solution 1, fails in Python 2.x if MyException contains 🔥
    # with UnicodeEncodeError: 'ascii' codec can't encode characters in position 24-25: ordinal not in range(128)
    print(my)  # outputs 'my detailed description'

### Solution 2
# Works in Python 2.x if exception only has ASCII characters,
# should always work in Python 3.x
str(my)

### Solution 3
# Required in Python 2.x if you need to handle non-ASCII characters,
# such as δσφφδσ (as pointed out by jjc) or emoji 🔥 💕 🎁 💯 🌹
# but does not work in Python 3.x
unicode(my)

A volte le eccezioni hanno più di un argomento, in modo da my.args[0] non è garantito per fornire tutte le informazioni del caso.

Per esempio:

# Python 2.7
try:
    u'\u12345'.encode('utf-8').encode('utf-8')
except UnicodeDecodeError as e:
    print e.args[0]
    print e.args
    print str(e)

Stampe come output:

ascii
('ascii', '\xe1\x88\xb45', 0, 1, 'ordinal not in range(128)')
'ascii' codec can't decode byte 0xe1 in position 0: ordinal not in range(128)

Tuttavia si tratta di un commercio sensibile al contesto fuori, perché, per esempio:

# Python 2.7
>>> str(SyntaxError())
'None'
# 'None' compares True which might not be expected

Il consiglio di usare str (myexception) porta a problemi Unicode in Python 2.7, per esempio:.

str(Exception(u'δσφφδσ'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

: (

unicode(Exception(u'δσφφδσ')) 

funziona come previsto, ed è preferita nel caso in cui alcuni dei contenuti della stringa di errore include input dell'utente

Il post di pzrq dice di usare:

str(e)

Questo era esattamente quello che mi serviva.

(Se ci si trova in un ambiente unicode, sembra che:

unicode(e)

funzionerà, e sembra funzionare bene in un ambiente non-unicode)

Pzrq detto un sacco di altre cose buone, ma ho quasi perso la loro risposta a causa di tutte le cose buone. Dal momento che non ho 50 punti non posso commentare la loro risposta per cercare di attirare l'attenzione sul semplice soluzione che funziona, e dal momento che non ho 15 Non posso votare che rispondere, ma posso pubblicare (si sente indietro, ma vabbè) - ecco mi distacco - probabilmente perderà punti per quello ...

Dal momento che il mio punto è quello di attirare l'attenzione alla risposta di pzrq, per favore non si appannano e perdere in tutto il seguito. le prime righe di questo post sono i più importanti.

La mia storia:

Il problema sono venuto qui per stato, se si desidera catturare un'eccezione da una classe che si ha alcun controllo su - che cosa allora ??? Non ho certamente intenzione di creare una sottoclasse tutte le possibili classi mio codice usa nel tentativo di essere in grado di ottenere un messaggio fuori di tutte le possibili eccezioni!

Io sto usando:

except Exception as e:
   print '%s (%s)' % (e.message,type(e))

che, come tutti ormai sappiamo, dà il PO avvertimento chiesto (che mi ha portato qui), e questo, che pzrq dà come un modo per farlo:

except Exception as e:
   print '%s (%s)' % (str(e),type(e))

non l'ha fatto.

Non sono in un ambiente unicode, ma la risposta di JJC mi chiedo, così ho dovuto provare. In questo contesto, questo diventa:

except Exception as e:
   print '%s (%s)' % (unicode(e),type(e))

, che, con mia grande sorpresa, ha lavorato esattamente come str (e) -. Quindi, ora che è quello che sto usando

Non so se 'str (e) / unicode (e)' è il 'modo di Python approvato', ed io probabilmente scoprire perché questo non va bene quando arrivo a 3,0, ma si spera che la capacità per gestire un'eccezione imprevista (*) senza morire e ancora ottenere alcune informazioni da esso non potrà mai andare via ...

(*) Hmm. "Un'eccezione imprevista" - Credo di aver balbettato

!
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top