Python pdb.post_mortem for Post-Crash Debugging

The pdb.post_mortem() function in Python provides a powerful way to diagnose application failures by immediately launching an interactive debugging session after an unhandled exception occurs. Instead of relying on speculative logging or restarting the application with manual breakpoints, this function preserves the exact execution state at the moment of failure. It enables developers to inspect local and global variables, traverse the call stack, and pinpoint the root cause of an error in the frozen environment where the crash happened.

How pdb.post_mortem() Works

When Python encounters an exception, it generates a traceback object that contains the call stack, frame objects, and the line numbers executing when the failure occurred. Under standard execution, an uncaught exception terminates the process and prints this traceback to standard error.

pdb.post_mortem() intercepts this process by accepting a traceback object—typically retrieved via sys.exc_info()[2]—and loading the execution frame where the exception was raised into Python's interactive debugger (pdb). If no traceback argument is passed, it automatically retrieves the traceback of the exception currently being handled.

Basic Implementation with Try-Except

The most direct way to use post-mortem debugging is inside an except block:

import pdb

def divide(a, b):
    return a / b

try:
    divide(10, 0)
except ZeroDivisionError:
    pdb.post_mortem()

When the ZeroDivisionError is raised, execution transfers directly into the interactive PDB shell at the exact line inside divide(), giving you access to inspect a and b.

Automating Post-Mortem Debugging with sys.excepthook

Instead of wrapping code in explicit try...except blocks, you can configure Python to automatically drop into pdb.post_mortem() whenever any unhandled exception occurs by overriding sys.excepthook:

import sys
import pdb

def exception_handler(exc_type, exc_value, exc_traceback):
    # Ignore interactive keyboard interrupts
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    
    print(f"Unhandled exception: {exc_value}")
    pdb.post_mortem(exc_traceback)

sys.excepthook = exception_handler

With this hook in place, any fatal crash anywhere in your application immediately pauses the termination process and yields control to the PDB prompt.

Navigating the Post-Mortem Environment

Because the application has already crashed, the execution flow cannot be resumed; commands like next, step, or continue will either exit the debugger or have no forward path. However, you retain full read and evaluation access to the post-crash state: