Debugging Python with pdb or ipdb
Filed in: Python, VideoBlobbing
April 5, 2012
Python has a wonderful debugger called pdb you should use if you aren't already. If you're like me and prefer to not use an IDE, you could have a mess of print statements as you try to debug things. If you don't know about it, you should be using pdb. It makes debugging a far nicer experience.
Here's a little script I came up with to remove odd numbers from a list.
import unittest def remove_odd_numbers(): my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] for item in my_list: if item % 2 == 1: my_list.remove(item) return my_list class RunTests(unittest.TestCase): def test_remove_odd_numbers(self): a = remove_odd_numbers() for item in a: number = item % 2 self.assertEqual(number, 0) if __name__ == "__main__": unittest.main()
Yay, unit tests pass. What happens if I change that list to:
my_list = [0, 1, 3, 2, 4, 6, 5, 8, 7, 6, 10]
I run my unit tests and get
F ====================================================================== FAIL: test_remove_odd_numbers (__main__.RunTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "test.py", line 18, in test_remove_odd_numbers self.assertEqual(number, 0) AssertionError: 1 != 0 ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (failures=1)
Well shoot. We can use pdb to trace through the code. I prefer ipdb because of the iPython shell. You can install it with pip install ipdb. Drop import ipdb; ipdb.set_trace() into that remove_odd_numbers function and step through the code.
So after seeing we took a few too many stupid pills today, the code is refactored and works.
import unittest from copy import copy def remove_odd_numbers(): my_list = [0, 1, 3, 2, 4, 6, 5, 8, 7, 6, 10] _my_list = copy(my_list) for item in _my_list: if item % 2 == 1: my_list.remove(item) return my_list class RunTests(unittest.TestCase): def test_remove_odd_numbers(self): a = remove_odd_numbers() for item in a: number = item % 2 self.assertEqual(number, 0) if __name__ == "__main__": unittest.main()
Here's a video showing how I stepped through to figure out what was going on.
This is just scratching the surface of what you can do with pdb and ipdb. As you get into it, check the manual (link below). It will make your programming life happier.