Wednesday, July 20, 2011

Changing a local variable in the Python debugger

Dave stopped by my office the other day and asked me how to do that, and I told him I wasn't sure. I seemed to remember having some difficulty with it in the past, but I also knew it was supposed to work. So I played with it while he watched.

After some confusion, he suggested the answer: if you modify the variable, don't look at it again; just continue. Sure enough, it works:

$ python
Python 2.6.5 (r265:79063, Jul  5 2010, 11:47:21) 
[GCC 4.5.0 20100604 [gcc-4_5-branch revision 160292]] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pdb
>>> import foo
>>> pdb.run('foo.main()')
> (1)()
(Pdb) s
--Call--
> /mnt/home/collin/foo.py(3)main()
-> def main():
(Pdb) l
  1   #!/usr/bin/python
  2   
  3  -> def main():
  4       x = "foo"
  5       if x == "foo":
  6           print "still foo"
  7       else:
  8           print "x changed to", x
  9   
 10   if __name__ == '__main__':
 11       main()
(Pdb) n
> /mnt/home/collin/foo.py(4)main()
-> x = "foo"                         We're about to execute line 4
(Pdb) n
> /mnt/home/collin/foo.py(5)main()
-> if x == "foo":                    x has been assigned the value "foo", and now we're about to test it
(Pdb) x='bar'                        I'm changing it to 'bar'
(Pdb) c                              and now I say "continue"
x changed to bar                     test at line 5 failed; we execute line 8
By the way, 'single' and "double" quotes mean the same thing in Python (unlike in Perl for example, or C). Anyway, now watch me ruin it. Continuing from where we left off:
>>> pdb.run('foo.main()')
> (1)()
(Pdb) s
--Call--
> /mnt/home/collin/foo.py(3)main()
-> def main():
(Pdb) n
> /mnt/home/collin/foo.py(4)main()
-> x = "foo"
(Pdb) n
> /mnt/home/collin/foo.py(5)main()
-> if x == "foo":                    We haven't executed line 5 yet
(Pdb) x='bar'                        Change it to 'bar'
(Pdb) x                              Examine it. What happens?
'foo'                                Examining it cancels out the change I just made.
(Pdb) x='bar'                        Was I hallucinating? Try again!
(Pdb) x                              ... and look again.
'foo'                                Ugh, just like last time.
(Pdb) c                              So the debugger thinks value's unchanged; what does the program think?
still foo                            The program thinks x still equals 'foo'
This is apparently a long-standing issue, dating back at least to this 2004 thread on the topic (prettier link). Are Dave and I the last two people in the world to hear about this?

No comments: