Pretty and more helpful exceptions in Python, automatically.
Install python_exception_best via pip:
pip install python_exception_bestAnd set the PYTHON_EXCEPTION_BEST environment variable to any value:
export PYTHON_EXCEPTION_BEST=1 # Linux / OSX
setx PYTHON_EXCEPTION_BEST 1 # WindowsThat's it!
In order to use python_exception_best in the Python REPL, first install the package (as instructed above) and run:
$ python -m python_exception_best
Type "help", "copyright", "credits" or "license" for more information.
(BetterExceptionsConsole)
>>>in order to drop into a python_exception_best-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 python_exception_best
python_exception_best.MAX_LENGTH = NoneWhile using python_exception_best in production, do not forget to unset the PYTHON_EXCEPTION_BEST variable to avoid leaking sensitive data in your logs.
If you want to use python_exception_best to format unittest's exception output, you can use the monkey patch below:
import sys
import unittest
import better_exceptions
def 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 = patchNote 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 MIDDLEWARE setting and update your logging configuration:
# ...
MIDDLEWARE = [
# ...
"python_exception_best.integrations.django.BetterExceptionsMiddleware",
]
# ...
from python_exception_best.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
# python-exception-best. 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 python-exception-best 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 $PYTHON_EXCEPTION_BEST (Linux / OSX) or echo %PYTHON_EXCEPTION_BEST% (Windows). On Linux and OSX, the export command does not add the variable permanently, you will probably need to edit the ~/.profile file to make it persistent. On Windows, you need to open a new terminal after the setx command.
Check that there is no conflict with another library, and that the sys.excepthook function has been correctly replaced with the python_exception_best's one. Sometimes other components can set up their own exception handlers, such as the python3-apport Ubuntu package that you may need to uninstall.
Make sure that you have not inadvertently deleted the python_exception_best_hook.pth file that should be in the same place as the python_exception_best folder where all of your Python packages are installed. Otherwise, try re-installing python_exception_best.
You can also try to manually activate the hook by adding import python_exception_best; python_exception_best.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 python_exception_best versions, OS, code snippet, interpreter, etc.) so that we can reproduce the bug you are experiencing.
Copyright © 2017, Josh Junon. Licensed under the MIT license.
