5 Tricks That Will Help You Debug Python Code
Tags: programming
Published: 2020-11-05 00:29:43

---
title: 5 Tricks That Will Help You Debug Python Code
published: true
date: 2020-11-02 08:21:30 UTC
tags: Programming
canonical_url: https://coderscat.com/5-tricks-that-will-help-you-debug-python-code
---

<section>
<div>
<div>
<p data-selectable-paragraph=""><img src="https://coderscat.com/wp-content/uploads/jo-szczepanska-9OKGEVJiTKk-unsplash-300x200.jpg" alt="" width="542" height="361" srcset="https://coderscat.com/wp-content/uploads/jo-szczepanska-9OKGEVJiTKk-unsplash-300x200.jpg 300w, https://coderscat.com/wp-content/uploads/jo-szczepanska-9OKGEVJiTKk-unsplash-1024x683.jpg 1024w, https://coderscat.com/wp-content/uploads/jo-szczepanska-9OKGEVJiTKk-unsplash-768x512.jpg 768w, https://coderscat.com/wp-content/uploads/jo-szczepanska-9OKGEVJiTKk-unsplash-1536x1024.jpg 1536w, https://coderscat.com/wp-content/uploads/jo-szczepanska-9OKGEVJiTKk-unsplash-2048x1365.jpg 2048w, https://coderscat.com/wp-content/uploads/jo-szczepanska-9OKGEVJiTKk-unsplash-930x620.jpg 930w" sizes="(max-width: 542px) 100vw, 542px"></p>
<p id="0f0a" data-selectable-paragraph="">Debugging is a fundamental skill for programmers, it’s a craft and we need to practice to be better at it. Here, I summarized the useful tricks and tools for debugging your Python code.</p>
<h1 id="8a32" data-selectable-paragraph="">#1 View the source code of a function or object</h1>
<p id="bc60" data-selectable-paragraph="">Know the details of implementation is critical in debugging. When you are debugging a Python code, you may want to know the source code of a module, class, method, function, traceback, frame, or code object. The <strong><em>inspect</em></strong> module will help you:</p>
<pre><span id="85e6" data-selectable-paragraph="">import inspect
def add(x, y):
    return x + y</span><span id="8404" data-selectable-paragraph="">class Dog:
    kind = 'dog' # class variable shared by all instances
    def __init__ (self, name):
        self.name = name # instance variable unique to each instance</span><span id="be61" data-selectable-paragraph=""> def eat(food):
        print("eating ..." + food)</span><span id="3acd" data-selectable-paragraph="">print(inspect.getsource(add))    
print(inspect.getsource(Dog))
print(inspect.getsource(Dog.eat))</span></pre>
<h1 id="5d36" data-selectable-paragraph="">#2 Print log into File</h1>
<p id="bc6e" data-selectable-paragraph=""><em>The log</em> is the most important clue for us to understanding the runtime of code. Printing out log is a useful way to follow the program’s execution flow.</p>
<p id="5308" data-selectable-paragraph="">However, <em>print</em> in Python only outputs to a terminal. It’s far from ideal for complex troubleshooting, especially for server-side applications.</p>
<p id="2a6c" data-selectable-paragraph="">The <em>print</em> function in Python 3 is much more powerful because it can take more arguments, and specifying some arguments can output the contents of print to a log file.</p>
<pre><span id="e3e2" data-selectable-paragraph="">with open('test.log', mode='w') as f:
    print('hello, python', file=f, flush=True)</span></pre>
<p id="051c" data-selectable-paragraph="">Another useful and flexible module is <em>logging</em>, we could set the output filename, log format, etc..</p>
<pre><span id="b5c9" data-selectable-paragraph="">import logging</span><span id="42ca" data-selectable-paragraph="">logging.basicConfig(filename='app.log', filemode='w', 
		format='%(name)s - %(levelname)s - %(message)s')
a = 5
b = 0
try:
  c = a / b
except Exception as e:
  logging.exception("Exception occurred")</span></pre>
<p id="4426" data-selectable-paragraph="">For more usage please refer to <a href="https://docs.python.org/3/library/logging.html" rel="noopener nofollow" target="_blank">logging — Logging facility for Python — Python 3.9.0 documentation</a></p>
<h1 id="f283" data-selectable-paragraph="">#3 Track the execution time</h1>
<p id="3ecb" data-selectable-paragraph="">For performance issues, we need to calculate the run time of a function. You might achieve it like this:</p>
<pre><span id="f212" data-selectable-paragraph="">import time</span><span id="e29f" data-selectable-paragraph="">start = time.time()
# run the function
end = time.time()</span><span id="5b59" data-selectable-paragraph="">print(end-start)</span></pre>
<p id="2244" data-selectable-paragraph="">There’s a built-in module called <em>timeit</em>, we could use it to track the time with only one line of code:</p>
<pre><span id="1abd" data-selectable-paragraph="">import time
import timeit</span><span id="9c08" data-selectable-paragraph="">def run_sleep(second):
    print(second)
    time.sleep(second)</span><span id="e1f0" data-selectable-paragraph="">print(timeit.timeit(lambda :run_sleep(2), number=1))</span></pre>
<h1 id="fde6" data-selectable-paragraph="">#4 Interactive debugging</h1>
<p id="2234" data-selectable-paragraph="">REPL supports an incremental, interactive development style, and interactive debugging is a more efficient way. The ideal workflow is the repeated process of edit-run.</p>
<p id="76d5" data-selectable-paragraph="">To invoke a program with an interactive session, we need to add<em> the -i</em> option:</p>
<pre><span id="142f" data-selectable-paragraph="">python -i demo.py</span></pre>
<p id="e49b" data-selectable-paragraph="">To make your life easier, <em>importlib.reload(module)</em> is a suitable way to avoid restart the interactive session.</p>
<p id="398b" data-selectable-paragraph="">Let’s take an example, suppose we are run a function called demo, to fix an issue we need to make some changes for this function, then <em>reload(module)</em> will load the modified version of demo without restart our session:</p>
<pre><span id="5c91" data-selectable-paragraph="">&gt;&gt;&gt; from importlib import reload
&gt;&gt;&gt; import demo from module
&gt;&gt;&gt; demo()
"The result of demo..."</span><span id="e241" data-selectable-paragraph=""># Make some changes to "demo"
&gt;&gt;&gt; demo()
"The result of demo..." # The Outdated result
&gt;&gt;&gt; reload(module) # Reload "module" after changes made to "demo"
&gt;&gt;&gt; demo()
"This will be the new result..."</span><span id="c2d8" data-selectable-paragraph="">&gt;&gt;&gt; # repeat the circle of fix-and-retry</span></pre>
<p id="44cc" data-selectable-paragraph="">This will save much time for debugging.</p>
<h1 id="ccc7" data-selectable-paragraph="">#5 Use pdb</h1>
<p id="0281" data-selectable-paragraph="">Python has a module called <strong><em>pdb</em></strong> to support interactive source code debugger. It supports setting breakpoints, single stepping at the line level. In addition, <strong><em>pdb</em></strong> print inspection of stack frames, values of variables, inspect source code, etc.</p>
<p id="e099" data-selectable-paragraph="">To start a program with a debugger, add -m <strong>pdb</strong> option for invoking scripts:</p>
<pre><span id="bc1e" data-selectable-paragraph="">user@coderscat:~/snippets$ python3.7 -m pdb demo.py 
&gt; /home/user/snippets/demo.py(1)&lt;module&gt;()
-&gt; import inspect
(Pdb) l
  1 -&gt; import inspect
  2  
  3 def gcd(a,b):
  4 if(b==0):
  5 return a
  6 else:
  7 return gcd(b,a%b)
  8  
  9  
 10 print(gcd(34, 34))
[EOF]
(Pdb) b demo.py:3
Breakpoint 1 at /home/user/snippets/demo.py:3
(Pdb) c
&gt; /home/user/snippets/demo.py(3)&lt;module&gt;()
-&gt; def gcd(a,b):
(Pdb) step
&gt; /home/user/snippets/demo.py(10)&lt;module&gt;()
-&gt; print(gcd(34, 34))
(Pdb)</span></pre>
<p id="b235" data-selectable-paragraph="">Another typical usage to break into the debugger from a running program is to insert:</p>
<pre><span id="3225" data-selectable-paragraph="">import pdb; pdb.set_trace()
</span></pre>
<p id="9b70" data-selectable-paragraph="">Here are some useful <em>pdb</em> command</p>
<ul>
<li id="80ae" data-selectable-paragraph="">list(l): show you the code line the Python interpreter is currently on</li>
<li id="b9b4" data-selectable-paragraph="">step(s): continue the execution line by line, step in function</li>
<li id="dce6" data-selectable-paragraph="">next(n) : continue the next line of code</li>
<li id="8175" data-selectable-paragraph="">break(b) : setup new breakpoint on current line</li>
<li id="d4cc" data-selectable-paragraph="">continue(c) : continue execution until next breakpoint</li>
</ul>
<p id="3072" data-selectable-paragraph="">In most cases, we don’t need to follow every step in execution, <em>pdb</em> is the ultimate tool for debugging Python program.</p>
</div>
</div>
</section>

<section>
<div>
<div>
<h1 id="f44c" data-selectable-paragraph="">Conclusion</h1>
<p id="0f15" data-selectable-paragraph="">When you debug Python code, have a try on these tricks and tools. To improve your skills in debugging, practice makes perfect!</p>
</div>
</div>
</section>

The post [5 Tricks That Will Help You Debug Python Code](https://coderscat.com/5-tricks-that-will-help-you-debug-python-code) appeared first on [Coder's Cat](https://coderscat.com).