Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Post-Mortem Debugging in Python allow for Stepping or Continuing?

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?

like image 923
Rocketman Avatar asked Dec 21 '12 17:12

Rocketman


1 Answers

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).

like image 105
Martijn Pieters Avatar answered Oct 19 '22 22:10

Martijn Pieters