I have been playing around with post-mortem debugging and am having some problems. Consider the following python script called example.py
:
k = 0
print 1. / k
print 'continue ...'
I can run this with:
> python -m pdb example.py
and then step to line 2 print 1. / k
and then set k = 1
and then continue with the pdb command c
.
Now if I do this with post-mortem debugging I am unable to continue program execution. I run with:
> python -i example.py
and then after I am dropped into the shell I do a:
import pdb
pdb.pm()
I am then able to change the value of k
as before, but I am unable to continue with any program execution. Pdb just simply exits.
I was unable to find anywhere that it explicitly states that you cannot step through a program in post-mortem. It appears to be the case. So then I would like to understand the value of post-mortem debugging. Is the only value to examine the state of the code when the error occurred?
A post-mortem is invoked when an exception has been thrown.
At that point, the stack is no longer 'active' and you cannot step through the code anymore. After all, an exception has just been thrown, signalling that the code path can no longer continue. What would you expect result
to be if you had the expression result = 1. / k
for example?
A literal Post-Mortem is used to see, after the patient has died (post mortem, in latin), what the cause of death was. A pdb post-mortem is no different. You get to see what the state of the program was at the moment of death, but you do not get to re-animate the deceased.
In other words, the purpose of a Post Mortem is to understand why the program has failed, by examining, in detail, what the program state was at the moment of failure.
The term has not been explicitly documented in the pdb manual probably because the term "Post Mortem" is thought to be in common use. The Wikipedia article on debugging mentions it in passing, and Python is not the only language that offers the technique; Windows debuggers offer the feature as well, R does so too, as do others.
If you were hoping to 're-animate' the corpse from the traceback, know that there are huge hurdles to overcome. While the traceback of an exception does include references to the global and local namespace of each frame in the stack, a live stack contains a lot more state that's not included in the traceback, state that can't be re-constructed. This includes closure cells attached to nested functions (especially when the parent function from which the closure originated is not itself part of the traceback), or the internal bookkeeping needed to handle try..except
, try..finally
or with
blocks, or the iterator object used by an active for
or async for
loop.
To those that were hoping otherwise, I say this: The program is passed on! This program is no more! It has ceased to be! 't's expired and gone to meet 'is maker! 't's a stiff! Bereft of life, 't rests in peace! If you hadn't nailed it to a traceback 't'd be pushing up the daisies! It's evaluation loop bookkeeping is now 'istory! 't's off the twig! It's kicked the bucket, 't's shuffled off its mortal coil, run down the curtain and joined the bleedin' choir invisible!! THIS IS AN EX-PROGRAM.
(With apologies to John Cleese and Michael Palin).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With