Skip to content

Instantly share code, notes, and snippets.

@awesomebytes
Created April 30, 2024 09:39
Show Gist options
  • Save awesomebytes/02dafc9821e3b1c480d19b66afe6d046 to your computer and use it in GitHub Desktop.
Save awesomebytes/02dafc9821e3b1c480d19b66afe6d046 to your computer and use it in GitHub Desktop.
Interactive debugging tips in Python with ipdb, hickle and ipython
#!/usr/bin/env python
"""Example of usage of ipython debugger (ipdb)
to interactively debug something in the code with autocomplete and color support.
You may need to install:
sudo pip install ipdb
"""
def my_func(my_arg):
# my_arg is a complex object that we don't know much about, maybe bad documentation or we are just lazy
# Let's imagine we have some complex logic that has a problem in the middle of it
for i in range(10):
if i == 7:
# You could print here and keep adding prints until you find what's wrong,
# which can be time consuming and frustrating
# You could also use your IDE's debugger (probably a better option), however,
# sometimes that's challenging too
print("There's an error here")
# So another option is to add an embedded debugger straight in the code (built-in functionality)
# import pdb; pdb.set_trace()
# The above would be the default way, but if you want autocompletion and color goodies from ipython
# I recommend the following (ignore fmt, it's for 'black' formatter to stop splitting into multiple lines)
import ipdb; ipdb.set_trace() # fmt: skip
# from IPython import embed; embed()
# Now you can play around with the state, check what is my_arg, modify it, and use 'continue'
# to let the code continue executing (or 'exit' to kill the program)
# tip1: you can use 'locals()' to see all local variables and 'globals()' to see all global
# tip2: you can use type() to know the type of something
if __name__ == "__main__":
# Let's call my_func with different arguments
my_func({"thing": 1, 123: "woah"})
my_func(456)
my_func(my_func)
#!/usr/bin/env python
"""Example of usage of ipython debugger (ipdb)
to interactively debug something in the code with autocomplete and color support.
Additionally, save to disk data by using hickle (a Pickle variant).
You may need to install:
sudo pip install ipdb
And for the hickle tip:
sudo pip install hickle
"""
def my_func(my_arg):
# my_arg is a complex object that we don't know much about, maybe bad documentation or we are just lazy
# Let's imagine we have some complex logic that has a problem in the middle of it
for i in range(10):
if i == 7:
print("There's an error here")
import ipdb; ipdb.set_trace() # fmt: skip
# tip3: save a variable to disk using hickle:
# import hickle; hickle.dump(my_arg, 'my_arg.hkl')
# import hickle; my_loaded_arg = hickle.load('my_arg.hkl')
# **Rabbit hole warning**: hickle is an improvement over dill, which is an improvement
# over pickle (the original serializer of data).
# hickle allows to save into hdf5 format which allows data to be opened and viewed in
# other languages and applications (including VSCode plugins)
# dill allows to save full Python interpreter sessions too
if __name__ == "__main__":
# Let's call my_func with different arguments
my_func({"thing": 1, 123: "woah"})
my_func(456)
my_func(my_func)
#!/usr/bin/env python
"""Example of usage of ipython embedded shell
to interactively debug something in the code with autocomplete and color support,
and also get all the extra capabilities (magic functions) of ipython, like:
* shell commands: output=! ls -1
* timing commands: %timeit my_func(123)
* embedded matplotlib support
* export to ipython notebook (.ipynb %notebook)
* etc (https://ipython.readthedocs.io/en/stable/interactive/magics.html)
HOWEVER, this is a separate interpreter, you will NOT be able to do 'continue'
and any modification to existing variables will not work
You may need to install:
sudo pip install ipython3
"""
def my_func(my_arg):
# my_arg is a complex object that we don't know much about, maybe bad documentation or we are just lazy
# Let's imagine we have some complex logic that has a problem in the middle of it
for i in range(10):
if i == 7:
print("There's an error here")
from IPython import embed; embed(colors="Linux") # fmt: skip
# current_folder_files = ! ls -1
# ['example_interactive_debugging_3.py', ...]
# %timeit str(my_arg)
# 371 ns ± 2.55 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
if __name__ == "__main__":
# Let's call my_func with different arguments
my_func({"thing": 1, 123: "woah"})
my_func(456)
my_func(my_func)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment