I get a warning that BaseException.message is deprecated in Python 2.6 when I use the following user-defined exception:
class MyException(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return repr(self.message)
This is the warning:
DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
self.message = message
What's wrong with this? What do I have to change to get rid of the deprecation warning?
Solution - almost no coding needed
Just inherit your exception class from Exception
and pass the message as the first parameter to the constructor
Example:
class MyException(Exception):
"""My documentation"""
try:
raise MyException('my detailed description')
except MyException as my:
print my # outputs 'my detailed description'
You can use str(my)
or (less elegant) my.args[0]
to access the custom message.
Background
In the newer versions of Python (from 2.6) we are supposed to inherit our custom exception classes from Exception which (starting from Python 2.5) inherits from BaseException. The background is described in detail in 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__
and __repr__
are already implemented in a meaningful way,
especially for the case of only one arg (that can be used as message).
You do not need to repeat __str__
or __init__
implementation or create _get_message
as suggested by others.
Yes, it's deprecated in Python 2.6 because it's going away in Python 3.0
BaseException class does not provide a way to store error message anymore. You'll have to implement it yourself. You can do this with a subclass that uses a property for storing the message.
class MyException(Exception):
def _get_message(self):
return self._message
def _set_message(self, message):
self._message = message
message = property(_get_message, _set_message)
Hope this helps
class MyException(Exception):
def __str__(self):
return repr(self.args[0])
e = MyException('asdf')
print e
This is your class in Python2.6 style. The new exception takes an arbitrary number of arguments.
How to replicate the warning
Let me clarify the problem, as one cannot replicate this with the question's sample code, this will replicate the warning in Python 2.6 and 2.7, if you have warnings turned on (via the -W
flag, the PYTHONWARNINGS
environment variable, or the warnings module):
>>> error = Exception('foobarbaz')
>>> error.message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foobarbaz'
Stop using .message
I prefer repr(error)
, which returns a string that contains the name of the error type, the repr of the message, if there is one, and the repr of the remaining arguments.
>>> repr(error)
"Exception('foobarbaz',)"
Eliminating the warning while still using .message
And the way you get rid of the DeprecationWarning
is to subclass a builtin exception as the Python designers intended:
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',)"
getting just the .message
attribute without error.message
If you know there was one argument, a message, to the Exception and that's what you want, it is preferable to avoid the message attribute and just take the str
of the error. Say for a subclassed Exception
:
class MyException(Exception):
'''demo straight subclass'''
And usage:
>>> myexception = MyException('my message')
>>> str(myexception)
'my message'
See also this answer:
Proper way to declare custom exceptions in modern Python?
As far as I can tell, simply using a different name for the message attribute avoids the conflict with the base class, and thus stops the deprecation warning:
class MyException(Exception):
def __init__(self, message):
self.msg = message
def __str__(self):
return repr(self.msg)
Seems like a hack to me.
Maybe someone can explain why the warning is issued even when the subclass defines a message attribute explicitly. If the base class no longer has this attribute, there shouldn't be a problem.
Continuing on from geekQ's answer, the preferred code replacement depends on what you need to do:
### 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