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_handlerWith 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:
- Stack Navigation: Use
u(up) andd(down) to move through the call stack frames to see how caller functions contributed to the failure. - Variable Inspection: Use
p <expression>orpp <expression>to print variable values, or calllocals()andglobals()to inspect environment dictionaries. - Context Inspection: Use
l(list) to view the source code surrounding the crash site. - Arbitrary Code Execution: Execute arbitrary Python expressions directly in the prompt to test hypothesis fixes or inspect deep object attributes.