Reputation: 10497
Python 2.7.10 appears to be converting my string into a tuple when thrown in an exception. Here's my example:
class MyError(RuntimeError):
def __init__(self, arg):
self.args = arg
def raiseMyError():
errorCode = 29
errorText = 'Port not ready yet'
exitCodeMessage = 'ERROR {0}: {1}'.format(errorCode, errorText)
# print exitCodeMessage --> print out here and it's a string
raise MyError(str(exitCodeMessage))
try:
raiseMyError()
except MyError as e:
print e.args
I create a string containing the error code and description and use this to construct a purpose built exception class. When I print out the exitCodeMessage
variable before the exception is created I get what I'd expect:
ERROR 29: Port not ready yet
However, the trace from within the exception handler gives me the following:
('E', 'R', 'R', 'O', 'R', ' ', '2', '9', ':', ' ', 'P', 'o', 'r', 't', ' ', 'n', 'o', 't',
' ', 'r', 'e', 'a', 'd', 'y', ' ', 'y', 'e', 't')
Can anyone tell me what's going on here and what I can do about it?
Upvotes: 3
Views: 1502
Reputation: 17725
Actually you don't need to override the __init__
method at all, it's sufficient enough to:
class MyError(RuntimeError):
pass
Regarding the behaviour - docs state that args
is:
The tuple of arguments given to the exception constructor.
When you inherit from Exception
class or any of it's children printing e.args
will simply print tuple(e.args)
, since args
property is defined in such way in the Exception
class (see @advance512 answer).
When you don't inherit from Exception
:
class MyError:
def __init__(self, arg):
self.args = arg
you don't inherit the "magic" behind the args
, thus calling e.args
will work as expected.
You could also write like this (note self.arg instead of self.args):
class MyError(RuntimeError):
def __init__(self, arg):
self.arg = arg
and calling e.arg
will also work as expected.
Upvotes: 3
Reputation: 1368
This is because args is a property that is defined in the BaseException
class.
Check out exceptions.py:70:
args = property(lambda self: tuple())
Try this:
class MyError(RuntimeError):
def __init__(self, errorString):
self._errorString = errorString
def raiseMyError():
errorCode = 29
errorText = 'Port not ready yet'
exitCodeMessage = 'ERROR %s: %s' % (errorCode, errorText)
# print exitCodeMessage --> print out here and it's a string
raise MyError(exitCodeMessage)
try:
raiseMyError()
except MyError as e:
print e._errorString
print e.args
output:
ERROR 29: Port not ready yet
()
Upvotes: 3