Change message of a caught Python exception (at least on Python 3.x, hopefully on 2.5+ too) - Python
[ Change message of a caught Python exception (at least on Python 3.x, hopefully on 2.5+ too) ]
Quite similar to the question "Getting the error message of an exception" except that I don't want to get the message out of the exception, I want to SET it.
Until recently, I thought I had a working solution involving changing my_exception.args
but i've just reached the limits trying to play with SyntaxError.
A bit of (bad) code to get things ready :
def get_exc(code):
"""Quick & dirty code to get exceptions."""
try:
exec(code)
except:
return sys.exc_info()
assert False
Then, getting a NameError exception, printing it, updating it, re-printing it, re-raising it : it seems like it works properly :
code = "foo = bar" # NameError("name 'bar' is not defined",)
error = get_exc(code)
type_, val, bt = error
print("Error", str(error), repr(error))
print("val", str(val), repr(val))
print("args", str(val.args), repr(val.args))
val.args = ("Setting val.args", )
print("Error", str(error), repr(error))
print("val", str(val), repr(val))
raise val
I can see the Setting val.args
message in the exception representation, its string conversion and when I raise it.
Trying to do the same with various other types of errors seems to be fine except for SyntaxError. First thing first, the exception has a few more attributes including msg
. Let's try to get the exception, print it, update it (both via msg
and args
), re-print it, re-raising it.
code = "return" # SyntaxError("'return' outside function", ('<string>', 1, 0, None))
error = get_exc(code)
type_, val, bt = error
print("Error", str(error), repr(error))
print("val", str(val), repr(val))
val.args = ("Setting val.args", val.args[1])
val.msg = "Setting val.msg"
print("Error", str(error), repr(error))
print("val", str(val), repr(val))
raise val
repr
displays Setting val.args
while str
and raise
display Setting val.msg
. How odd!
This leads to a few (quite related) questions :
why do we have the same information ("invalid syntax") in two places (
args
andmsg
).what is the actual working and recommanded way to update the message ? At the moment, I'm assuming something along the lines of "change
args
and if there is amsg
attribute, change it too" but I do not find this very beautiful nor am I sure that it will work for other types of Exceptions I might have not considered.
Additional reference : I've looked for a solution in PEP 352 - Required Superclass for Exceptions but I didn't find what I needed.
Edit:
To confirm accepted answer : print(val.msg is val.args[0]) # True
Answer 1
.args
is an attribute of BaseException
, and is usually just passed all of the arguments to the exception.
.msg
is the first argument, and is an attribute of SyntaxError
. It references the same string as given in .args
, if any.
what is the actual working and recommanded way to update the message ?
To not do so at all. Most of the time, one should just raise a new, chained exception.
There is also no way to do this for an arbitrary class, since they can have effectively any layout.