Make `sys.excepthook` settable with an environment variable -- analogous to `PYTHONBREAKPOINT`

There seem to be two main ways of inserting a debugger into a Python invocation:

  • builtins.breakpoint: open a debugger in an arbitrary place;
  • sys.excepthook: open a debugger post-mortem after an exception.

These are both exceptionally useful tools. However, at present only the former comes with an environment variable to configure it, namely PYTHONBREAKPOINT.

It would be great to additionally support a PYTHONEXCEPTHOOK environment variable, with essentially analogous semantics, whihc would allow easy configuration of this other entry point.

Current alternatives: right now, setting sys.excepthook in some “global” fashion isn’t actually possible.

  • There is usercustomize.py, but this is frequently not loaded - with good reason - when using per-project venvs. (site.ENABLE_USER_SITE being False)
  • There is PYTHONSTARTUP, but this is only loaded on interactive invocations of python. (And also isn’t loaded on python -i foo.py for some reason?)

(Besides which both of these are fairly deep magic for most users, and tricky to set up in a portable fashion.)

Is this something that would be of interest?

Why not just have a wrapper that sets the value and then invokes the normal entry point of the code? That’s only a few lines of code and is entirely “global” - the sys module is singleton, like anything else imported in the normal way.

What kind of wrapper are you suggesting? (E.g. something like some_package for which python -m some_package ...actual argv here... does the right thing?)

Unfortuantely I don’t know of any way in Python to “invoke the normal entry point of the code”. From within a currently-running Python runtime, how would you make that runtime go on to perform the equivalent of python ...arbitrary argv...; bearing in mind that those argv may include the full gamut of flags that Python supports?

I’m suggesting a few lines of Python code in a separate .py file within the project along the lines of

import sys
from pathlib import Path

def my_excepthook(exc_type, exc, traceback):
    ...

if __name__ == '__main__':
    sys.excepthook = my_excepthook
    with open(Path(__file__).parent / 'driver.py') as driver:
        main_source = driver.read()
    exec(main_source)
1 Like