AI Basics with AK

Season 02 - Introduction to Python Programming

Arun Koundinya Parasa

Episode 19

Python Debugging

Introduction to Python’s pdb Debugger

What is pdb?

  • pdb stands for Python Debugger, a built-in module that allows interactive debugging of Python programs.

Why Use pdb?

  • Interactive Exploration: Inspect variables and program flow at runtime.
  • Efficient Debugging: Set breakpoints and step through code without modifying it.
  • Enhanced Understanding: Gain deeper insights into how your code executes.

Essential Commands

Command Description
h or help Display help information.
n or next Execute the next line of code.
s or step Step into a function call.
r or return Continue execution until the current function returns.
c or continue Continue execution until the next breakpoint.
l or list Display source code around the current line.
ll List the entire source code for the current function or frame.
p expression Print the value of an expression.
pp expression Pretty-print the value of an expression.
w or where Show the current position in the call stack.
u or up Move up one level in the call stack.
d or down Move down one level in the call stack.
a or args Display the arguments of the current function.
q or quit Exit the debugger.

Simple Magic Command in Jupyter Notebook - 1

import math

def factorial(num):
    return math.factorial(num)
factorial(-1)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-10-5aae425d6a8b> in <cell line: 0>()
----> 1 factorial(-1)

<ipython-input-9-28ffe0ae4037> in factorial(num)
      2 
      3 def factorial(num):
----> 4     return math.factorial(num)

ValueError: factorial() not defined for negative values
%debug
> <ipython-input-9-28ffe0ae4037>(4)factorial()

      1 import math

      2 

      3 def factorial(num):

----> 4     return math.factorial(num)



ipdb> d

*** Newest frame

ipdb> d

*** Newest frame

ipdb> num

-1

ipdb> math.factorial(-1)

*** ValueError: factorial() not defined for negative values

ipdb> q

Simple Magic Command in Jupyter Notebook - 2

def calculate_modulo(n):
    for i in range(n, -1, -5):
        print(f"Calculating {n} % {i}")
        result = n % i
        print(f"Result: {result}")
    return result

calculate_modulo(0)
Calculating 0 % 0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-7-0149e7600626> in <cell line: 0>()
      6     return result
      7 
----> 8 calculate_modulo(0)

<ipython-input-7-0149e7600626> in calculate_modulo(n)
      2     for i in range(n, -1, -5):
      3         print(f"Calculating {n} % {i}")
----> 4         result = n % i
      5         print(f"Result: {result}")
      6     return result

ZeroDivisionError: integer modulo by zero
%debug
> <ipython-input-7-0149e7600626>(4)calculate_modulo()

      2     for i in range(n, -1, -5):

      3         print(f"Calculating {n} % {i}")

----> 4         result = n % i

      5         print(f"Result: {result}")

      6     return result



ipdb> display n

display n: 0

ipdb> display i

display i: 0

ipdb> 0 % 0

*** ZeroDivisionError: integer modulo by zero

ipdb> q

Simple Magic Command in Jupyter Notebook - 3

def process_data(data):
    processed = []
    for item in data:
        if item < 0:
            continue
        processed.append(item * 2)
    return processed

def calculate_statistics(numbers):
    total = sum(numbers)
    count = len(numbers)
    average = total / count if count != 0 else 0
    return total, average

def main():
    raw_data = [5, -3, 7, 0, -1, 4]

    cleaned_data = process_data(raw_data)

    total, average = calculate_statistics(cleaned_data)

    print(f"Total: {total}, Average: {average}")

main()
Total: 32, Average: 8.0
%debug
def process_data(data):
    processed = []
    for item in data:
        if item < 0:
            continue
        processed.append(item * 2)
    return processed

def calculate_statistics(numbers):
    total = sum(numbers)
    count = len(numbers) -1
    average = total / count
    return total, average

def main():
    raw_data = [0]

    cleaned_data = process_data(raw_data)

    total, average = calculate_statistics(cleaned_data)

    print(f"Total: {total}, Average: {average}")

main()
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-5-4a6579b6263c> in <cell line: 0>()
     22     print(f"Total: {total}, Average: {average}")
     23 
---> 24 main()

<ipython-input-5-4a6579b6263c> in main()
     18     cleaned_data = process_data(raw_data)
     19 
---> 20     total, average = calculate_statistics(cleaned_data)
     21 
     22     print(f"Total: {total}, Average: {average}")

<ipython-input-5-4a6579b6263c> in calculate_statistics(numbers)
     10     total = sum(numbers)
     11     count = len(numbers) -1
---> 12     average = total / count
     13     return total, average
     14 

ZeroDivisionError: division by zero

Final Slide

%debug
> <ipython-input-5-4a6579b6263c>(12)calculate_statistics()

     10     total = sum(numbers)

     11     count = len(numbers) -1

---> 12     average = total / count

     13     return total, average

     14 



ipdb> u

> <ipython-input-5-4a6579b6263c>(20)main()

     18     cleaned_data = process_data(raw_data)

     19 

---> 20     total, average = calculate_statistics(cleaned_data)

     21 

     22     print(f"Total: {total}, Average: {average}")



ipdb> d

> <ipython-input-5-4a6579b6263c>(12)calculate_statistics()

     10     total = sum(numbers)

     11     count = len(numbers) -1

---> 12     average = total / count

     13     return total, average

     14 



ipdb> total

0

ipdb> count

0

ipdb> 0 % 0

*** ZeroDivisionError: integer modulo by zero

ipdb> q

Thank You