Created
April 30, 2024 09:39
-
-
Save awesomebytes/02dafc9821e3b1c480d19b66afe6d046 to your computer and use it in GitHub Desktop.
Interactive debugging tips in Python with ipdb, hickle and ipython
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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