Reputation: 329
I want to generate a string in an exception handler that contains the name of the exception, and any arguments passed...oretty much the final output that one gets with Traceback.
For example, if raise bar.FnordError("message")
is called, in the exception handler, I want to produce the string: "bar.FnordError: message"
I want it to work for built in exceptions, as well as exceptions in the current and other modules. This is what I came up with, but it doesn't seem very pythonic.
def this_is_lame(err):
if type(err).__module__ in ['__main__', 'builtins']:
return "{}: {}".format(type(err).__name__, err)
else:
return "{}.{}: {}".format(type(err).__module__, type(err).__name__, err)
I've dug through the BaseException C code in python, and the Traceback standard library. I seem to be missing the correct "nice" accessor.
Is BaseException.__format__
documented anywhere? Are there escapes for it?
I've played around in the interpreter and nothing quite gives me what I want.
import sys
import traceback
import bar
try:
raise bar.FnordError("message")
except Exception as err:
print(type(err))
print(repr(err))
print(type(err).__module__)
print(type(err).__name__)
print(err)
print("this is what I want: '{}'".format(this_is_lame(err)))
print()
try:
raise ValueError("message")
except Exception as err:
print(type(err))
print(repr(err))
print(type(err).__module__)
print(type(err).__name__)
print("this is what I want: '{}'".format(this_is_lame(err)))
which produces:
$ python foo.py
<class 'bar.FnordError'>
FnordError('message',)
bar
FnordError
message
this is what I want: 'bar.FnordError: message'
<class 'ValueError'>
ValueError('message',)
builtins
ValueError
this is what I want: 'ValueError: message'
Upvotes: 5
Views: 3984
Reputation: 281843
There's no "nice" accessor. Python itself does something pretty similar to what you're doing in the default sys.excepthook
, although exceptions defined in __main__
print as __main__.WhateverException
.
If you want to see how Python itself does it, on Python 2, the check happens in PyErr_Display
, which checks strcmp(modstr, "exceptions")
:
moduleName = PyObject_GetAttrString(exception, "__module__");
if (moduleName == NULL)
err = PyFile_WriteString("<unknown>", f);
else {
char* modstr = PyString_AsString(moduleName);
if (modstr && strcmp(modstr, "exceptions"))
{
err = PyFile_WriteString(modstr, f);
err += PyFile_WriteString(".", f);
}
Py_DECREF(moduleName);
}
On Python 3, print_exception
checks _PyUnicode_CompareWithId(moduleName, &PyId_builtins)
.
moduleName = _PyObject_GetAttrId(type, &PyId___module__);
if (moduleName == NULL || !PyUnicode_Check(moduleName))
{
Py_XDECREF(moduleName);
err = PyFile_WriteString("<unknown>", f);
}
else {
if (_PyUnicode_CompareWithId(moduleName, &PyId_builtins) != 0)
{
err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW);
err += PyFile_WriteString(".", f);
}
Py_DECREF(moduleName);
}
Upvotes: 2