Prettify Python exception output to make it legible.

Related tags

Logging PrettyErrors
Overview

pretty-errors

Prettifies Python exception output to make it legible. Install it with

python -m pip install pretty_errors

If you want pretty_errors to be used whenever you run a python script you must add it to your python startup procedure. You can do so easily by running:

python -m pretty_errors

This is the recommended way to use pretty_errors; apart from being simpler and universal, using it will mean SyntaxError exceptions also get formatted prettily (which doesn't work if you are manually importing pretty_errors).


Example


If you have not installed it universally you can use it in your project simply by importing it:

import pretty_errors

Note you need to be running in a terminal capable of colour output in order to get colour output: in Windows this means powershell, cmder, etc. If you must use a monochrome terminal then you can call the helper function pretty_errors.mono(), which will set some config options in a way that is useful for monochrome output.

Monochrome

If you want to configure the output then use pretty_errors.configure(), pretty_errors.whitelist(), pretty_errors.blacklist(), pretty_errors.pathed_config(). For example:

import pretty_errors
pretty_errors.configure(
    separator_character = '*',
    filename_display    = pretty_errors.FILENAME_EXTENDED,
    line_number_first   = True,
    display_link        = True,
    lines_before        = 5,
    lines_after         = 2,
    line_color          = pretty_errors.RED + '> ' + pretty_errors.default_config.line_color,
    code_color          = '  ' + pretty_errors.default_config.line_color,
    truncate_code       = True,
    display_locals      = True
)
pretty_errors.blacklist('c:/python')

Result


Scraping STDERR

Sometimes it will be impossible for pretty_errors to utilize sys.excepthook: for instance, if you are using a framework which installs its own logging (such as uvicorn). In such cases, you can make pretty_errors scrape the output to stderr instead, replacing it with its own. To do so simple call:

pretty_errors.replace_stderr()

Note that this will lose some functionality, since pretty_errors will only have access to what is being output on screen, rather then the entire stack trace. A good API will generally have a way to interact with the exception stack, which will allow for using excepthook: replace_stderr should be the last resort. See this comment for an example


Whitelist / Blacklist:

You may use the functions whitelist(path) and blacklist(path) to add paths which will be necessary (whitelist) or excluded (blacklist). The top frame of the stack is never excluded.


Pathed Configurations

You may set up alternate configurations, which are triggered by the path to the code file of the frame. For example, if you were not interested in the system frames (those under 'c:/python') but did not want to hide them completely by using the blacklist you could do this:

meh = pretty_errors.config.copy()
meh.line_color = meh.code_color = meh.filename_color = meh.function_color = meh.line_number_color = (
    pretty_errors.GREY
)
pretty_errors.pathed_config(meh, 'c:/python')

Environment Variables
  • PYTHON_PRETTY_ERRORS
    You may disable pretty_errors by setting the environment variable PYTHON_PRETTY_ERRORS to 0. i.e. at a command prompt:
set PYTHON_PRETTY_ERRORS=0

Calling pretty_errors.activate() will override this.

If you wish to selectively utilize pretty_errors, then use the above, and in your code perform your calculation to determine whether or not to call pretty_errors.activate().

  • PYTHON_PRETTY_ERRORS_ISATTY_ONLY
    It may be desirable to disable pretty_errors when you are redirecting output to a file (to keep error logs, for instance). If you wish to do so, then setting PYTHON_PRETTY_ERRORS_ISATTY_ONLY to non-zero will cause pretty_errors to check if it is running in an interactive terminal, and only activate if so.
set PYTHON_PRETTY_ERRORS_ISATTY_ONLY=1

Setting this will disable replace_stderr() in the same situations, unless you call it with the force parameter: replace_stderr(force=True).

Calling pretty_errors.activate() will override this.

You may check pretty_errors.terminal_is_interactive to see if the terminal is interactive (pretty_errors sets this by checking sys.stderr.isatty()). You can use this to select a different config. For example:

if not pretty_errors.terminal_is_interactive:
    pretty_errors.mono()

Configuration settings:

Configuration settings are stored in pretty_errors.config, though should be set using pretty_errors.configure(). A reference for the default config is stored in pretty_errors.default_config.

  • name
    Optional field to store config name in.

  • line_length
    Output will be wrapped at this point. If set to 0 (which is the default) it will automatically match your console width.

  • full_line_newline
    Insert a hard newline even if the line is full. If line_length is the same as your console width and this is enabled then you will see double newlines when the line is exactly full, so usually you would only set this if they are different.

  • separator_character
    Character used to create the header line. Hyphen is used by default. If set to None or '' then header will be disabled.

  • display_timestamp
    When enabled a timestamp is written in the traceback header.

  • timestamp_function
    Function called to generate timestamp. Default is time.perf_counter.

  • exception_above
    When enabled the exception is displayed above the stack trace.

  • exception_below
    When enabled the exception is displayed below the stack trace.

  • stack_depth
    The maximum number of entries from the stack trace to display. When 0 will display the entire stack, which is the default.

  • top_first
    When enabled the stack trace will be reversed, displaying the top of the stack first.

  • always_display_bottom
    When enabled (which is the default) the bottom frame of the stack trace will always be displayed.

  • show_suppressed
    When enabled all suppressed exceptions in the stack trace will be shown (typically they are suppressed because an exception above them has replaced them). The normal python behaviour is to hide them.

  • filename_display
    How the filename is displayed: may be pretty_errors.FILENAME_COMPACT, pretty_errors.FILENAME_EXTENDED, or pretty_errors.FILENAME_FULL

  • line_number_first
    When enabled the line number will be displayed first, rather than the filename.

  • display_link
    When enabled a link is written below the error location, which VSCode will allow you to click on.

  • lines_after, lines_before
    How many lines of code to display for the top frame, before and after the line the exception occurred on.

  • trace_lines_after, trace_lines_before
    How many lines of code to display for each other frame in the stack trace, before and after the line the exception occurred on.

  • truncate_code
    When enabled each line of code will be truncated to fit the line length.

  • display_locals
    When enabled, local variables appearing in the top stack frame code will be displayed with their values.

  • display_trace_locals
    When enabled, local variables appearing in other stack frame code will be displayed with their values.

  • truncate_locals
    When enabled the values of displayed local variables will be truncated to fit the line length.

  • display_arrow
    When enabled an arrow will be displayed for syntax errors, pointing at the offending token.

  • arrow_head_character, arrow_tail_character
    Characters used to draw the arrow which points at syntax errors.

  • inner_exception_message
    Message displayed when one exception occurs inside another, between the two exceptions. Default is None, which will simply display the exceptions separated by the header. If you want to emulate the default non-pretty behaviour, use this:

inner_exception_message = pretty_errors.MAGENTA + "\n During handling of the above exception, another exception occurred:\n"

Note that if you use top_first then the order will be reversed, so you should use a message like this instead:

inner_exception_message = pretty_errors.MAGENTA + "\n The above exception occurred during another exception:\n"

  • inner_exception_separator
    Default is False. When set to True a header will be written before the inner_exception_message.

  • prefix
    Text string which is displayed at the top of the report, just below the header.

  • infix
    Text string which is displayed between each frame of the stack.

  • postfix
    Text string which is displayed at the bottom of the exception report.

  • reset_stdout
    When enabled the reset escape sequence will be written to stdout as well as stderr; turn this on if your console is being left with the wrong color.


These color strings will be output before the relevant part of the exception message. You may include non-escape sequence strings if you wish; if you do not have a terminal which supports color output, or simply want to include extra demarcation.

  • header_color
    Escape sequence to set header color.

  • timestamp_color
    Escape sequence to set timestamp color.

  • exception_color
    Escape sequence to set exception color.

  • exception_arg_color
    Escape sequence to set exception arguments color.

  • exception_file_color
    Escape sequence to set color of filenames in exceptions (for example, in a FileNotFoundError).

  • filename_color
    Escape sequence to set filename color.

  • line_number_color
    Escape sequence to set line number color.

  • function_color
    Escape sequence to set function color.

  • link_color
    Escape sequence to set link color.

  • line_color
    Escape sequence to set the color of the line of code which caused the exception.

  • code_color
    Escape sequence to set the color of other displayed lines of code.

  • arrow_head_color, arrow_tail_color
    Escape sequence to set the color of the arrow which points at syntax errors.

  • syntax_error_color
    Escape sequence to set the color of the syntax error token.

  • local_name_color
    Escape sequence to set the color of local variable names.

  • local_value_color
    Escape sequence to set the color of local variable values.

  • local_len_color
    Escape sequence to set the color of local value length when local is truncated.

pretty_errors has some built in escape sequence constants you can use when setting these colors:

  • BLACK
  • GREY
  • RED
  • GREEN
  • YELLOW
  • BLUE
  • MAGENTA
  • CYAN
  • WHITE

For each color there is a matching BRIGHT_ variant (i.e. pretty_errors.BRIGHT_RED), as well as a _BACKGROUND variant to set the background color (i.e. pretty_errors.RED_BACKGROUND).

For example:

pretty_errors.configure(
    line_color = pretty_errors.CYAN_BACKGROUND + pretty_errors.BRIGHT_WHITE
)

Further customization

For the most extensive customization (short of forking the package) you may override the default ExceptionWriter class, allowing you to tailor the output however you wish. Typically you will only need to override the write_ methods.

For example:

class MyExceptionWriter(pretty_errors.ExceptionWriter):
    def write_header(self):
        self.output_text('######## ERROR ########')

pretty_errors.exception_writer = MyExceptionWriter()

Run help(pretty_errors.ExceptionWriter) in the python interpreter for more details.

Issues
  • Only last Exception shown

    Only last Exception shown

    While dealing with multiple exceptions ("During handling of the above exception, another exception occurred: ..."), Pretty Errors will show only the last one.

    Is there a way to show all of them?

    opened by pmatias 13
  • Use *.pth file instead of sitecustomize.py

    Use *.pth file instead of sitecustomize.py

    The site-packages/sitecustomize.py file is not reliable loaded for everybody. To ensure pretty_errors is loaded after python -m pretty_errors, create a site-packages/pretty_errors.pth file containing:

    import pretty_errors; pretty_errors.configure() # if you add option here, keep it on one line
    

    If you don't want to use a *.pth, at least use /home/user/.local/lib/python3.7/site-packages/usercustomize.py, which is more likely to be imported and is meant for things like this. But *customize.py files are not imported in venv, which makes them pretty useless for real life Python usage.

    opened by ksamuel 9
  • Does not work in the IDLE shell

    Does not work in the IDLE shell

    The shell of the IDLE editor shipped with Python supports colors. It would be great to add support for it.

    opened by mardukbp 7
  • Error using global install script with venv

    Error using global install script with venv

    Attempting the global install via python -m pretty_errors under a virtual environment with path C:\venvs\flask results in this trace:

    runpy.py 193 _run_module_as_main "main", mod_spec)

    runpy.py 85 _run_code exec(code, run_globals)

    main.py 133 found = find_install(True)

    main.py 66 find_install for path in getallsitepackages():

    main.py 54 getallsitepackages return getsitepackages() + getusersitepackages()

    main.py 42 getsitepackages pattern = re.compile(r'^%s$' % os.path.join(os.environ['VIRTUAL_ENV'], 'lib', 'python[0-9.]+', 'site-packages'))re.py 233 compile return _compile(pattern, flags)

    re.py 301 _compile p = sre_compile.compile(pattern, flags)

    sre_compile.py 562 compile p = sre_parse.parse(p, flags)

    sre_parse.py 855 parse p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0)

    sre_parse.py 416 _parse_sub not nested and not items))

    sre_parse.py 502 _parse code = _escape(source, this, state)

    sre_parse.py 401 _escape raise source.error("bad escape %s" % escape, len(escape))

    sre_constants.error: bad escape \l at position 15

    I attempted to fix by using the method described in another issue, changing regex pattern to allow backslashes in path. But then there is no option to install anywhere:

    (flask) C:\Users\dkornacki\rtc-workspace\iSeries Python\iSeries Python\square_po_import>python -m pretty_errors

    To have pretty_errors be used when you run any python file you may add it to your usercustomize.py (user level) or sitecustomize.py (system level), or to pretty_errors.pth.

    (just hit to accept the defaults if you are unsure)

    Choose folder to install into:

    0: Exit

    Option: [default: 0]

    opened by dkornacki-cutco 7
  • May need better integration with ASGI/WSGI servers

    May need better integration with ASGI/WSGI servers

    Hello there, I'd like to use pretty errors in my web development, but I have some issues.

    I use the fastapi framework, which runs multi processes through the ASGI uvicorn server. Doesn't matter what I do (import, setup config, usercustomize.py etc.) errors do not get pretty in this context. They do when I run my normal scripts.

    Can I ask for help/directions?

    opened by pdonorio 6
  • How to fully uninstall pretty_errors in all conda env?

    How to fully uninstall pretty_errors in all conda env?

    Hi~, When I installed pretty_errors via pip, I inadvertently chose let it act on all my envs. Therefore, how can I fully uninstall it or do something to fix it? Thank u~

    opened by pengzhiliang 4
  • Running pretty_errors as script with virtualenv does not find install folders

    Running pretty_errors as script with virtualenv does not find install folders

    I'm on Ubuntu 20.04 and attempting to install pretty_errors using the python -m pretty_errors -s -p command within a virtualenv. Upon running the command, I get the following output:

    To have pretty_errors be used when you run any python file you may add it to your usercustomize.py (user level) 
    or sitecustomize.py (system level), or to pretty_errors.pth.
    
    (just hit <enter> to accept the defaults if you are unsure)
    
    
     Choose folder to install into:
    
    0: Exit
    
    Option: [default: 0]
    

    After which I hit enter and the install fails. Investigating the __main__.py file along with Issue #38 lead me to the following function on line 41

    def getsitepackages():
        pattern1 = re.compile(r'^%s$' % re.escape(os.path.join(os.environ['VIRTUAL_ENV'], 'lib', 'python[0-9.]+', 'site-packages')))
        pattern2 = re.compile(r'^%s$' % re.escape(os.path.join(os.environ['VIRTUAL_ENV'], 'lib', 'site-packages')))
        paths = [path for path in set(sys.path) if pattern1.search(path) or pattern2.search(path)]
        return paths
    

    Using some basic debugging, I discovered that the paths variable returned was completely empty, despite the fact that pattern1 should have match my virtualenv path: /home/username/.virtualenvs/general/lib/python3.9/site-packages I traced the source of this error to the call to re.escape in pattern1. The os.path.join call returns /home/username/.virtualenvs/general/lib/python[0-9.]+/site-packages as expected, but the call to re.escape returns the string '/home/username/\\.virtualenvs/general/lib/python\\[0\\-9\\.\\]\\+/site\\-packages'. Because re.escape escapes all regex special characters, the python[0-9]+ portion of the regex gets mangled and causes pattern1.search to fail. Omitting the call to re.escape matches the string as expected. Upon removing the call to re.escape and running python -m pretty_errors -s -p again, everything installed and functioned as expected.

    >>> import os, sys, re
    >>> sys.path
    ['', '/usr/lib/python39.zip', '/usr/lib/python3.9', '/usr/lib/python3.9/lib-dynload', '/home/username/.virtualenvs/general/lib/python3.9/site-packages']
    >>> venv_path = sys.path[-1]
    >>> os.path.join(os.environ['VIRTUAL_ENV'], 'lib', 'python[0-9.]+', 'site-packages')
    '/home/username/.virtualenvs/general/lib/python[0-9.]+/site-packages'
    >>> pattern1_escape = re.compile(r'^%s$' % re.escape(os.path.join(os.environ['VIRTUAL_ENV'], 'lib', 'python[0-9.]+', 'site-packages')))
    >>> pattern1_escape.search(venv_path)
    >>> pattern1_no_escape = re.compile(r'^%s$' % os.path.join(os.environ['VIRTUAL_ENV'], 'lib', 'python[0-9.]+', 'site-packages'))
    >>> pattern1_no_escape.search(venv_path)
    <re.Match object; span=(0, 61), match='/home/username/.virtualenvs/general/lib/python3.9/s>
    >>> pattern1_no_escape.search(venv_path).group(0)
    '/home/username/.virtualenvs/general/lib/python3.9/site-packages'
    

    Here is my pyvenv.cfg file for Python and virtualenv info:

    home = /usr
    implementation = CPython
    version_info = 3.9.5.final.0
    virtualenv = 20.4.6
    include-system-site-packages = false
    base-prefix = /usr
    base-exec-prefix = /usr
    base-executable = /usr/bin/python3.9
    
    opened by KittyKittyKitKat 3
  • Missing import time  in usercustomize.py

    Missing import time in usercustomize.py

    When trying to change configs globally by uncommenting the pretty_errors.configure( in usercustomize.py, an error is thrown since time is not imported, but is used in timestamp_function = time.perf_counter.

    On my end, I've just added import time to the top of the file; however, when generating the file import time should be added as well.

    opened by dchen327 3
  • pretty_errors not working without explicit import.

    pretty_errors not working without explicit import.

    Hi, I ran sudo python -m pretty_errors and tried installing both sitecustomize.py and pretty_errors.pth (not at the same time) but, pretty_errors does not seem to work.

    When installing either of the files, I installed them at /usr/local/lib/python3.8/dist-packages.

    With "sitecustomize.py" it simply does not have any effect. With "pretty_errors.pth" it shows error

    Error processing line 2 of /usr/local/lib/python3.8/dist-packages/pretty_errors.pth:
    
      Traceback (most recent call last):
        File "/usr/lib/python3.8/site.py", line 175, in addpackage
          exec(line)
        File "<string>", line 1, in <module>
        File "/usr/local/lib/python3.8/dist-packages/pretty_errors/__init__.py", line 1, in <module>
          import sys, re, colorama, os, time, linecache
      ModuleNotFoundError: No module named 'colorama'
    

    Even though, Colorama is installed and I the latest version. How do I solve this issue?

    opened by nisarg-ujjainkar 3
  • fix bug: module 'site' has no attribute 'getsitepackages'  in virtualenv

    fix bug: module 'site' has no attribute 'getsitepackages' in virtualenv

    support virtualenv

    1. fix bug: in virtualenv, run python -m pretty_errors [option] throws
      AttributeError:
      module 'site' has no attribute 'getsitepackages'
    2. when run python -m pretty_errors, support displaying sitecustomize.py
      or pretty_errors.pth according to the path you selected before.
    opened by hyliang96 3
  • [Question] Can PrettyErrors handle pdb's output?

    [Question] Can PrettyErrors handle pdb's output?

    Is it possible to have PrettyErrors handle exception outputs when using Python's pdb?

    I've used the following code to import PrettyErrors

    import pretty_errors
    pretty_errors.replace_stderr() 
    

    but when adding breakpoints within the code the output is not being interpreted. E.g when running python -m pdb -c continue myscript.py

    opened by MrBeardedGuy 0
Owner
Iain King
Game developer.
Iain King
Colored terminal output for Python's logging module

coloredlogs: Colored terminal output for Python's logging module The coloredlogs package enables colored terminal output for Python's logging module.

Peter Odding 448 Jan 14, 2022
A Python library that tees the standard output & standard error from the current process to files on disk, while preserving terminal semantics

A Python library that tees the standard output & standard error from the current process to files on disk, while preserving terminal semantics (so breakpoint(), etc work as normal)

Greg Brockman 4 Jan 7, 2022
Outlog it's a library to make logging a simple task

outlog Outlog it's a library to make logging a simple task!. I'm a lazy python user, the times that i do logging on my apps it's hard to do, a lot of

ZSendokame 1 Jan 16, 2022
Pretty-print tabular data in Python, a library and a command-line utility. Repository migrated from bitbucket.org/astanin/python-tabulate.

python-tabulate Pretty-print tabular data in Python, a library and a command-line utility. The main use cases of the library are: printing small table

Sergey Astanin 1.1k Jan 21, 2022
Progressbar 2 - A progress bar for Python 2 and Python 3 - "pip install progressbar2"

Text progress bar library for Python. Travis status: Coverage: Install The package can be installed through pip (this is the recommended method): pip

Rick van Hattem 747 Jan 18, 2022
Python logging made (stupidly) simple

Loguru is a library which aims to bring enjoyable logging in Python. Did you ever feel lazy about configuring a logger and used print() instead?... I

null 10.8k Jan 21, 2022
The new Python SDK for Sentry.io

sentry-python - Sentry SDK for Python This is the next line of the Python SDK for Sentry, intended to replace the raven package on PyPI. from sentry_s

Sentry 1.1k Jan 22, 2022
A Fast, Extensible Progress Bar for Python and CLI

tqdm tqdm derives from the Arabic word taqaddum (تقدّم) which can mean "progress," and is an abbreviation for "I love you so much" in Spanish (te quie

tqdm developers 20.9k Jan 21, 2022
Rich is a Python library for rich text and beautiful formatting in the terminal.

Rich 中文 readme • lengua española readme • Läs på svenska Rich is a Python library for rich text and beautiful formatting in the terminal. The Rich API

Will McGugan 33.9k Jan 21, 2022
Structured Logging for Python

structlog makes logging in Python faster, less painful, and more powerful by adding structure to your log entries. It's up to you whether you want str

Hynek Schlawack 1.9k Jan 22, 2022
Json Formatter for the standard python logger

Overview This library is provided to allow standard python logging to output log data as json objects. With JSON we can make our logs more readable by

Zakaria Zajac 1.2k Jan 20, 2022
A colored formatter for the python logging module

Log formatting with colors! colorlog.ColoredFormatter is a formatter for use with Python's logging module that outputs records using terminal colors.

Sam Clements 727 Jan 14, 2022
Pretty and useful exceptions in Python, automatically.

better-exceptions Pretty and more helpful exceptions in Python, automatically. Usage Install better_exceptions via pip: $ pip install better_exception

Qix 4.1k Jan 18, 2022
Debugging-friendly exceptions for Python

Better tracebacks This is a more helpful version of Python's built-in exception message: It shows more code context and the current values of nearby v

Clemens Korndörfer 1.2k Jan 14, 2022
A small utility to pretty-print Python tracebacks. ⛺

TBVaccine TBVaccine is a utility that pretty-prints Python tracebacks. It automatically highlights lines you care about and deemphasizes lines you don

Stavros Korokithakis 365 Dec 29, 2021
A cool logging replacement for Python.

Welcome to Logbook Travis AppVeyor Supported Versions Latest Version Test Coverage Logbook is a nice logging replacement. It should be easy to setup,

null 1.4k Jan 21, 2022
ClusterMonitor - a very simple python script which monitors and records the CPU and RAM consumption of submitted cluster jobs

ClusterMonitor A very simple python script which monitors and records the CPU and RAM consumption of submitted cluster jobs. Usage To start recording

null 23 Oct 4, 2021
Json Formatter for the standard python logger

This library is provided to allow standard python logging to output log data as json objects. With JSON we can make our logs more readable by machines and we can stop writing custom parsers for syslog type records.

Zakaria Zajac 1k Jul 14, 2021
A simple, transparent, open-source key logger, written in Python, for tracking your own key-usage statistics.

A simple, transparent, open-source key logger, written in Python, for tracking your own key-usage statistics, originally intended for keyboard layout optimization.

Ga68 31 Jan 2, 2022