Reputation: 339
I define my own exception
class MyException(Exception):
pass
somewhere deep in project folder structure, i.e. project\subfolder_1\subfolder_2\etc...\exceptions.py and then use it
from project.subproject.subfolder_1.subfolder_2.\etc ... .exceptions import MyException as MyException
and then raise it as raise MyException('bad stuff happened')
it is then displayed in output as
project.subproject.subfolder_1.subfolder_2.etc... .exceptions.MyException: bad stuff happened
can I somehow get rid of the full namespace? Since it's anyway 'imported as' and in code referred only as MyException, to display just
MyException: bad stuff happened
as with other built in exceptions?
Upvotes: 0
Views: 51
Reputation: 4368
When a Python exception has to be printed, its __str__
method gets called (or those of its parents if has not defined one).
file: so75195149/deeply_nested.py
class MyCustomException(Exception): pass
file: main.py
from so75195149.deeply_nested import MyCustomException
raise MyCustomException("bad stuff happened")
gives
Traceback (most recent call last):
File "main.py", line 3, in <module>
raise MyCustomException("bad stuff happened")
so75195149.deeply_nested.MyCustomException: bad stuff happened
If you define a __str__
method :
file: so75195149/deeply_nested.py
class MyCustomException(Exception):
def __str__(self) -> str:
return "Hello"
you get instead
Traceback (most recent call last):
File "/home/stack_overflow/main.py", line 3, in <module>
raise MyCustomException("bad stuff happened")
so75195149.deeply_nested.MyCustomException: Hello
because you can only choose how the exception is printed, but all the rest comes from the fact that your program crashed (uncaught exception), so Python nicely give you information about that by calling its sys.excepthook
:
This function prints out a given traceback and exception to
sys.stderr
.
When an exception is raised and uncaught, the interpreter callssys.excepthook
with three arguments, the exception class, exception instance, and a traceback object. [...] in a Python program this happens just before the program exits. The handling of such top-level exceptions can be customized by assigning another three-argument function tosys.excepthook
.
Here we go :
file: main.py
import sys
def my_custom_excepthook(exception_class, exception_instance, traceback_object):
print(f"sys.excepthook called\n{exception_class=!r}\n{exception_instance=!s}\n{traceback_object=!s}", file=sys.stderr)
sys.excepthook = my_custom_excepthook
from so75195149.deeply_nested import MyCustomException
raise MyCustomException("bad stuff happened")
produces
sys.excepthook called
exception_class=<class 'so75195149.deeply_nested.MyCustomException'>
exception_instance=Hello
traceback_object=<traceback object at 0x7f79515fe200>
So if you want something that looks like the usual way Python prints, using previous answers :
file: main.py
import sys
import traceback
def my_custom_excepthook(exception_class, exception_instance, traceback_object):
# do not use traceback.format_exception
print("Traceback (most recent call last):", file=sys.stderr)
traceback.print_tb(traceback_object, file=sys.stderr)
print(f"{exception_class.__name__}: {exception_instance!s}", file=sys.stderr)
sys.excepthook = my_custom_excepthook
from so75195149.deeply_nested import MyCustomException
raise MyCustomException("bad stuff happened")
gives
Traceback (most recent call last):
File "/home/stack_overflow/main.py", line 15, in <module>
raise MyCustomException("bad stuff happened")
MyCustomException: Hello
versus the original :
Traceback (most recent call last):
File "/home/stack_overflow/main.py", line 13, in <module>
raise MyCustomException("bad stuff happened")
so75195149.deeply_nested.MyCustomException: Hello
See traceback.format_exception
and qualified name (__qualname__
) for more information.
But I advise you to be careful in setting a custom excepthook. If another exception crashes the program, you won't get its qualified name, which is very often useful (the reason it is included by default). It is global for the whole Pyhton app.
I recommend instead to wrap your custom exceptions in a non-deeply-neested-defined exception. Or do not use custom-defined exceptions, use the standard ones.
Upvotes: 1