Explain Codes LogoExplain Codes Logo

Starting python debugger automatically on error

python
prompt-engineering
debugging
exception-handling
Anton ShumikhinbyAnton Shumikhin·Dec 30, 2024
TLDR

Auto-start the Python debugger, pdb, when an error occurs by configuring sys.excepthook. This function is called by Python when an uncaught exception occurs. Configuring it to call pdb.post_mortem() with the traceback of the exception will dive into the post-mortem debugging mode right where the error occurred:

import sys import pdb def handle_exception(exc_type, exc_value, exc_traceback): if sys.stdin.isatty() and sys.stdout.isatty() and sys.stderr.isatty(): # 'tty' in 'isatty' stands for teletype. Nothing to do with tiny bowties, sorry. pdb.post_mortem(exc_traceback) sys.excepthook = handle_exception # This line is as explosive as kombucha left fermenting too long: # 1 / 0

To enhance your debugging experience, give IPython a go which provides some handy features over pdb when used with its %pdb command. It not only offers syntax highlighting but also gives a more interactive interface.

Another way is to run a script in interactive mode using python -i your_script.py. This leaves the session open after an exception, letting you inspect variables post-error.

To remove the need for setting breakpoints manually, the use of pdb -c continue comes in handy:

python -m pdb -c continue your_script.py

Setting up a separate debugging module with your sys.excepthook convergence eases the pdb integration into different scripts and creates a sort of debugging focal point.

Exception handling using pdb's post-mortem

Best foot (post-mortem debugging) forward

Learn the ropes of post-mortem debugging with pdb.post_mortem(). Find yourself a traceback object as a map and blaze a trail to the point the exception was raised:

import traceback import pdb try: result = some_calculations() except Exception: exc_info = sys.exc_info() traceback.print_exc() # Now printing traceback or as I call it, the breadcrumbs pdb.post_mortem(exc_info[2]) # Starting the debugging journey

Let's interact (command line fashion)

For a more interactive command line, include code.interact in your utility belt, holding tightly on to the local context:

import code try: problematic_function() except Exception: # Summoning the magical interactive shell code.interact(local=dict(globals(), **locals()))

Lambdas are your friends

Let lambda traverse the traceback frames on a sleigh and slide right into the last frame's context:

import pdb import sys # Riding the traceback coaster down lambda_traceback_rider = lambda: pdb.post_mortem(sys.exc_info()[2]) sys.excepthook = lambda *exc_info: lambda_traceback_rider()

Go with the flow (with custom modules)

Use a custom module for debugging for a smoother sail across various scripts. It not only sets a configuration for sys.excepthook but also adds reusable debugging utilities.

Checking all right boxes before debugging

Feel the rhythm (of interactive mode)

Before you let Pandora out of the box, ensure to check if you are in an interactive mode or if your script is being run from a tty device:

if sys.stdin.isatty() and sys.stdout.isatty() and sys.stderr.isatty(): sys.excepthook = handle_exception else: # Welp, not a right place for debugging party

Your ticket please (printing traceback)

Hold up, before diving into the debugging ocean, get the lay of the land (or rather seas) by printing the exception's traceback:

import traceback import pdb import sys def handle_exception(exc_type, exc_value, exc_traceback): traceback.print_exception(exc_type, exc_value, exc_traceback) pdb.post_mortem(exc_traceback) sys.excepthook = handle_exception

Debugger Airbag: 🛑🔧

  • Deploys on impact (Error in code)
  • Softens the blow (Simplifies debugging)
  • Instant inspection of the crash site (Immediate problem identification)

Amping your debugging game

A better platform with IPython

Welcome syntax highlighting and code completion during backtrace, with IPython, using %pdb magic command.

Debugging by error type

Customize your exception handling based on specific error types to concentrate on tangled issues:

def handle_value_error(exc_type, exc_value, exc_traceback): if isinstance(exc_value, ValueError): pdb.post_mortem(exc_traceback) sys.excepthook = handle_value_error

Conditional debugging

Shield your production code from the debugging code by conditional enabling of debugging using environment variables:

if os.getenv('DEBUG'): sys.excepthook = handle_exception

Advanced goodies

Make the most of advanced features such as conditional breakpoints, watchpoints, and remote debugging.