Pregunta

recibo una advertencia de que BaseException.message está en desuso en Python 2.6 cuando se utiliza la siguiente excepción definida por el usuario:

class MyException(Exception):

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

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

Esta es la advertencia:

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

¿Qué hay de malo en esto? ¿Qué tengo que cambiar para deshacerse de la advertencia desaprobación?

¿Fue útil?

Solución

Solución - casi ninguna codificación necesaria

Sólo heredar su clase de excepción de Exception y pasar el mensaje como el primer parámetro al constructor

Ejemplo:

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

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

Puede utilizar str(my) o (menos elegante) my.args[0] para acceder al mensaje personalizado.

Fondo

En las nuevas versiones de Python (de 2.6) que se supone que heredarán nuestros clases de excepción personalizados de excepción que ( a partir de Python 2.5 ) hereda de BaseException. El fondo se describe en detalle en 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__ y __repr__ ya están implementadas de una manera significativa, especialmente para el caso de sólo una arg (que puede ser utilizado como mensaje).

No es necesario repetir __str__ o __init__ aplicación o crear _get_message según lo sugerido por otros.

Otros consejos

Sí, está en desuso en Python 2.6, ya que va a desaparecer en Python 3.0

BaseException clase no proporciona una manera de almacenar mensajes de error más. Vas a tener que aplicar por sí mismo. Usted puede hacer esto con una subclase que utiliza una propiedad para almacenar el mensaje.

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

Espero que esto ayude

class MyException(Exception):

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

e = MyException('asdf')
print e

Esta es la clase de estilo Python2.6. La nueva excepción toma un número arbitrario de argumentos.

¿Cómo replicar La advertencia

Permítanme aclarar el problema, ya que no se puede replicar esto con código de ejemplo de la cuestión, esto va a replicar la advertencia en Python 2.6 y 2.7, si tiene advertencias activada (a través de la bandera -W , PYTHONWARNINGS variable de entorno, o la módulo advertencias):

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

Deje de usar .message

Yo prefiero repr(error), que devuelve una cadena que contiene el nombre del tipo de error, el repr del mensaje, si lo hay, y la repr de los argumentos restantes.

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

La eliminación de la advertencia sin dejar de utilizar .message

Y la forma en que recibe eliminar de la DeprecationWarning es una subclase de una excepción de orden interna como los diseñadores de Python por objeto:

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',)"

obtener sólo el atributo .message sin error.message

Si sabe que era un argumento, un mensaje, a la excepción y eso es lo que quiere, es preferible evitar el atributo del mensaje y acaba de tomar la str del error. Digamos por un Exception subclases:

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

Y uso:

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

Vea también esta respuesta:

manera adecuada para declarar excepciones personalizadas en Python moderna?

Por lo que yo puedo decir, simplemente usando un nombre diferente para el atributo del mensaje evita el conflicto con la clase base, y por lo tanto se detiene el aviso de desaprobación:

class MyException(Exception):

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

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

Parece un truco para mí.

Tal vez alguien puede explicar por qué se emitió la advertencia incluso cuando la subclase define un mensaje de atributos de forma explícita. Si la clase base ya no tiene este atributo, no debería ser un problema.

de geekQ respuesta , la sustitución de código preferido depende de lo que tiene que hacer:

### 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 veces excepciones tienen más de un argumento, por lo my.args[0] no está garantizada para proporcionar toda la información relevante.

Por ejemplo:

# 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)

Prints como salida:

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)

Sin embargo se trata de un comercio fuera sensible al contexto, porque, por ejemplo:

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

El consejo de usar str (MyException) conduce a problemas Unicode en Python 2.7, por ejemplo:.

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'δσφφδσ')) 

funciona como se esperaba, y se prefiere en los casos en que algunos de los contenidos de la cadena de error incluye la entrada del usuario

El post de pzrq dice a utilizar:

str(e)

Esto era exactamente lo que necesitaba.

(Si se encuentra en un entorno Unicode, se observe que:

unicode(e)

va a funcionar, y parece que funciona bien en un entorno no-Unicode)

Pzrq dijo un montón de otras cosas buenas, pero casi perdió su respuesta debido a todas las cosas buenas. Dado que no tengo 50 puntos que no puedo comentar en su respuesta a intentar llamar la atención sobre la solución simple que funciona, y como yo no tengo 15 No puedo votar que contestar, pero me pueden enviar (se siente hacia atrás, pero oh bien) - así que aquí estoy publicando - probablemente perderá puntos por eso ...

Desde mi punto es llamar la atención sobre la respuesta de pzrq, por favor no se ponen vidriosos y se pierda en todo el siguiente. las primeras líneas de este post son los más importantes.

Mi historia:

El problema Vine aquí por era si desea capturar una excepción de una clase que no tiene ningún control sobre - lo que entonces ??? Desde luego, no voy a subclase todas las clases posibles usos mi código en un intento de ser capaz de obtener un mensaje de todas las excepciones posibles!

Yo estaba usando:

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

que, como todos sabemos ahora, da la OP advertencia se le preguntó sobre (lo que me ha traído hasta aquí), y esto, que pzrq da como una forma de hacerlo:

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

no lo hizo.

No estoy en un entorno Unicode, pero la respuesta de JJC me hizo pensar, así que tuve que probarlo. En este contexto, esto se convierte en:

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

, que, para mi sorpresa, funcionó exactamente como str (e) -. Ahora que es lo que estoy utilizando

No sé si 'str (e) / Unicode (e)' es la 'manera Python aprobado', y probablemente voy a averiguar por qué eso no es bueno cuando llegue a 3.0, pero se espera que la capacidad para manejar una excepción inesperada (*) sin morir y aún así obtener alguna información de que se os ocurra ir lejos ...

(*) Hmm. "Excepción inesperada" - Creo que sólo tartamudeaba

!
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top