Pretty and useful exceptions in Python, automatically.
Pretty and more helpful exceptions in Python, automatically.
Install
better_exceptionsvia pip:
$ pip install better_exceptions
And set the
BETTER_EXCEPTIONSenvironment variable to any value:
export BETTER_EXCEPTIONS=1 # Linux / OSX setx BETTER_EXCEPTIONS 1 # Windows
That's it!
In order to use
better_exceptionsin the Python REPL, first install the package (as instructed above) and run:
$ python -m better_exceptions Type "help", "copyright", "credits" or "license" for more information. (BetterExceptionsConsole) >>>
in order to drop into a
better_exceptions-enabled Python interactive shell.
If you want to allow the entirety of values to be outputted instead of being truncated to a certain amount of characters:
import better_exceptions better_exceptions.MAX_LENGTH = None
While using
better_exceptionsin production, do not forget to unset the
BETTER_EXCEPTIONSvariable to avoid leaking sensitive data in your logs.
If you want to use
better_exceptionsto format
unittest's exception output, you can use the monkey patch below:
import sys import unittest import better_exceptionsdef patch(self, err, test): lines = better_exceptions.format_exception(*err) if sys.version_info[0] == 2: return u"".join(lines).encode("utf-8") return "".join(lines)
unittest.result.TestResult._exc_info_to_string = patch
Note that this uses an undocumented method override, so it is not guaranteed to work on all platforms or versions of Python.
In
settings.py, add your new class to the
MIDDLEWAREsetting and update your logging configuration:
# ...MIDDLEWARE = [ # ... "better_exceptions.integrations.django.BetterExceptionsMiddleware", ]
...
from better_exceptions.integrations.django import skip_errors_filter
if you don't want to override LOGGING because you want to change the default,
you can vendor Django's default logging configuration and update it for
better-exceptions. the default for Django 3.1.4 can be found here:
https://github.com/django/django/blob/3.1.4/django/utils/log.py#L13-L63
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'filters': { 'skip_errors': { '()': 'django.utils.log.CallbackFilter', 'callback': skip_errors_filter, } }, 'handlers': { 'console': { 'level': 'INFO', # without the 'filters' key, Django will log errors twice: # one time from better-exceptions and one time from Django. # with the 'skip_errors' filter, we remove the repeat log # from Django, which is unformatted. 'filters': ['skip_errors'], 'class': 'logging.StreamHandler', } }, 'loggers': { 'django': { 'handlers': [ 'console', ], } } }
example output:
If you do not see beautiful exceptions, first make sure that the environment variable does exist. You can try
echo $BETTER_EXCEPTIONS(Linux / OSX) or
echo %BETTER_EXCEPTIONS%(Windows). On Linux and OSX, the
exportcommand does not add the variable permanently, you will probably need to edit the
~/.profilefile to make it persistent. On Windows, you need to open a new terminal after the
setxcommand.
Check that there is no conflict with another library, and that the
sys.excepthookfunction has been correctly replaced with the
better_exceptions's one. Sometimes other components can set up their own exception handlers, such as the
python3-apportUbuntu package that you may need to uninstall.
Make sure that you have not inadvertently deleted the
better_exceptions_hook.pthfile that should be in the same place as the
better_exceptionsfolder where all of your Python packages are installed. Otherwise, try re-installing
better_exceptions.
You can also try to manually activate the hook by adding
import better_exceptions; better_exceptions.hook()at the beginning of your script.
Finally, if you still can not get this module to work, open a new issue by describing your problem precisely and detailing your configuration (Python and
better_exceptionsversions, OS, code snippet, interpeter, etc.) so that we can reproduce the bug you are experiencing.
Copyright © 2017, Josh Junon. Licensed under the MIT license.