DEV Community

Cover image for Debug Python code interactively
Michael Interface
Michael Interface

Posted on

Debug Python code interactively

The debugging process using print statements can get very tedious especially when you don’t really know where the issue might be. Also running the same script multiple times with lots of print statements after each slight change in the code can be time consuming.

The disadvantages with print debugging:

  • Lots of print statements that only output info about script state for the current run
  • Lack of knowledge about the state of the whole script
  • Inability to alter the script for a quick test in the same run

Wouldn't it be nice to make the debugging experience more interactive?


TLDR

Debugging python scripts using python interactive console.

Start you python script in interactive mode: python -i my_script.py

Use python built in code module to drop inside interactive console from you python code:

code.interact(
    banner='Start interactive mode',
    local=locals(),
    exitmsg='Exiting interactive mode')
Enter fullscreen mode Exit fullscreen mode

Interactive mode

You can run your python scripts in interactive mode using the -i parameter in the command line.

# example_sript.py

class Person:
    def __init__(self, age):
        self.age = age

age_list = [19, 4, 55, 14]
person_list = [Person(age=age) for age in age_list]

def display_age_rating():
    for person in person_list:
        if person.age < 18:
            print(f"The content is rated 'M' for mature and can not be shown to a {person.age} year old.")
        else:
            print(f"Being {person.age} year you fall under the mature age group.")

Enter fullscreen mode Exit fullscreen mode

Now run it from inside of your console:

python -i example_sript.py
>>> 
Enter fullscreen mode Exit fullscreen mode

From here you get all the advantages of using python interactive console.

  • Checkout the values of your local variables:
>>> age_list
[19, 4, 55, 14]
Enter fullscreen mode Exit fullscreen mode
  • Invoke functions:
>>> display_age_rating()
Being 19 year you fall under the mature age group.
The content is rated 'M' for mature and can not be shown to a 4 year old.
Being 55 year you fall under the mature age group.
The content is rated 'M' for mature and can not be shown to a 14 year old.
Enter fullscreen mode Exit fullscreen mode
  • Change your program state for quick testing:
>>> age_list = [100]*4
>>> age_list
[100, 100, 100, 100]
>>> person_list = [Person(age=age) for age in age_list]
>>> display_age_rating()
Being 100 year you fall under the mature age group.
Being 100 year you fall under the mature age group.
Being 100 year you fall under the mature age group.
Being 100 year you fall under the mature age group.
Enter fullscreen mode Exit fullscreen mode

Use Ctrl+D or type in exit() and press enter to quit the interactive python console.

This method makes debugging experience much more flexible compared to print debugging. But what if you need to debug not a single script but a whole application with multiple files?


Dropping inside interactive mode from inside the code

The built in code python module will allow us to drop inside interactive mode from anywhere in our code during the script execution. To do that we need to invoke interact() function in our script.

# Import code module
import code

class Person:
    def __init__(self, age):
        self.age = age

age_list = [19, 4, 55, 14]
person_list = [Person(age=age) for age in age_list]

def display_age_rating():
    for age in age_list:
        if age < 18:
            print(f"The content is rated 'M' for mature and can not be shown to a {age} year old.")
        else:
            print(f"Being {age} year you fall under the mature age group.")

code.interact(
    banner='Start interactive mode before invoking display_age_rating',
    local=locals(),
    exitmsg='Exiting interactive mode')

display_age_rating()
Enter fullscreen mode Exit fullscreen mode

interact() creates an InteractiveConsole instance. This pauses the execution of the script and starts the read-eval-print loop. It takes in four parameters:

  • banner accepts a string which will be displayed at the start of the interactive mode instance
  • local sets a default namespace for the interpreter loop
  • readfunc can be used as the InteractiveConsole.raw_input() method if provided
  • exitmsg accepts a string which will be displayed after exiting interactive mode instance

💡 For the local parameter we can manually provide a dictionary of local or global variables that we can access inside interactive mode instance
local={’age_list’: age_list}

Now we can start our small program and use the interactive console the same way as if we provided the -i parameter mentioned previously.

python3 interactive_mode.py                                                                                            
Start interactive mode before invoking display_age_rating
>>> age_list
[19, 4, 55, 14]
>>> display_age_rating()
Being 19 year you fall under the mature age group.
The content is rated 'M' for mature and can not be shown to a 4 year old.
Being 55 year you fall under the mature age group.
The content is rated 'M' for mature and can not be shown to a 14 year old.
>>>
Enter fullscreen mode Exit fullscreen mode

By pressing Ctrl+D we exit current interactive session and let our program finish executing

>>> 
Exiting interactive mode
Being 19 year you fall under the mature age group.
The content is rated 'M' for mature and can not be shown to a 4 year old.
Being 55 year you fall under the mature age group.
The content is rated 'M' for mature and can not be shown to a 14 year old.
Enter fullscreen mode Exit fullscreen mode

We are able to enter interactive console from different parts of our code by placing the interact() function where needed.

import code

age_list = [19, 4, 55, 14]

def display_age_rating():
    for age in age_list:
        code.interact(
            banner='age_list loop iteration',
            local=locals(),
            exitmsg='Exiting interactive mode')

        if age < 18:
            print(f"The content is rated 'M' for mature and can not be shown to a {age} year old.")
        else:
            print(f"Being {age} year you fall under the mature age group.")

code.interact(
    banner='Start interactive mode before invoking display_age_rating',
    local=locals(),
    exitmsg='Exiting interactive mode')
display_age_rating()

Enter fullscreen mode Exit fullscreen mode

That way we are able to jump to the next point of our scripts execution by pressing Ctrl+D.

python3 interactive_mode.py                                                                                       
Start interactive mode before invoking display_age_rating
>>> age_list
[19, 4, 55, 14]
>>> 
Exiting interactive mode
age_list loop iteration
>>> person.age
19
>>> person.age = 100
>>> person.age
100
>>> 
Exiting interactive mode
Being 100 year you fall under the mature age group.
age_list loop iteration
>>> person.age
4
>>> 
Exiting interactive mode
The content is rated 'M' for mature and can not be shown to a 4 year old.
age_list loop iteration
>>>...
Enter fullscreen mode Exit fullscreen mode

To quit the interactive mode use exit().


Conclusion

Python interactive console safes time debugging our code by letting us check the code state and change it on the fly. The code module provides a more flexible way to interact with our code and better understand it’s behavior. For more info check our the official documentation of the code module.

Hopefully this post was helpful. I’d like to now what tools and approaches do you use for debugging your python code. Feel free to comment down below.

Top comments (0)