The new pdbp (Pdb+) Python debugger!
Tags: python, debugging, pdb, pytest
Published: 2023-08-03 01:38:01

---
title: The new pdbp (Pdb+) Python debugger!
published: true
description: pdbp (Pdb+) is a new debugger for Python.
tags: Python, debugging, pdb, pytest
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o0daisitht0nxpuiuvi4.png
# Use a ratio of 100:42 for best results.
# published_at: 2023-08-03 00:23 +0000
---

<h3>Meet <a class="notranslate" href="https://github.com/mdmintz/pdbp">pdbp</a> (Pdb+) — a new Python debugger!</h3>

![pdbp (Pdb+) debugger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jvvjnaxpci1rsbcsgdy.png)

<figcaption id="caption-attachment-400" class="wp-caption-text">pdbp (Pdb+) debugging example</figcaption>

<img src="https://seleniumbase.github.io/cdn/gif/coffee_pdbp.gif" alt="SeleniumBase test with the pdbp (Pdb+) debugger" title="SeleniumBase test with the pdbp (Pdb+) debugger" data-canonical-src="https://seleniumbase.github.io/cdn/gif/coffee_pdbp.gif" style="max-width: 100%; display: inline-block;" data-target="animated-image.originalImage">

<figcaption id="caption-attachment-394" class="wp-caption-text">SeleniumBase testing the Coffee Cart app with pdbp</figcaption><div />

<div /><h4>Why not just use Python’s built-in <a class="notranslate" href="https://docs.python.org/3/library/pdb.html">pdb</a> debugger or another existing one like <a href="https://github.com/gotcha/ipdb">ipdb</a> or <a href="https://github.com/pdbpp/pdbpp">pdbpp</a>?</h4><div />

<p>Starting with <code class="notranslate">pdb</code>, it has a limited display with no color and limited abilities. Here’s Python’s built-in <code class="notranslate">pdb</code> debugger:</p><div />

![Regular pdb](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n7eld4svrqdbikh2hsyp.png)

<figcaption id="caption-attachment-386" class="wp-caption-text">Regular pdb debugger</figcaption></figure>

<p>The <code class="notranslate">ipdb</code> debugger added tab completion, syntax highlighting, better tracebacks, etc. (<a href="https://seleniumbase.com/the-ultimate-pytest-debugging-guide-2021/">I talked about it in a past blog post.</a>) Here’s a sample of how it looks:</p>

![ipdb debugger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lwwe47bji73wv8nngjzf.png)

<figcaption id="caption-attachment-389" class="wp-caption-text">ipdb debugger</figcaption></figure>

<p>The major drawback is that it comes with a high number of external dependencies that take time to download. Here’s a <a href="https://github.com/tox-dev/pipdeptree">pipdeptree</a> for <code class="notranslate">ipdb</code> dependencies:</p>

<pre class="notranslate">&gt; pipdeptree
ipdb==0.13.13
├── decorator [required: Any, installed: 5.1.1]
└── ipython [required: &gt;=7.31.1, installed: 8.14.0]
    ├── appnope [required: Any, installed: 0.1.3]
    ├── backcall [required: Any, installed: 0.2.0]
    ├── decorator [required: Any, installed: 5.1.1]
    ├── jedi [required: &gt;=0.16, installed: 0.18.2]
    │   └── parso [required: &gt;=0.8.0,&lt;0.9.0, installed: 0.8.3] ├── matplotlib-inline [required: Any, installed: 0.1.6] │ └── traitlets [required: Any, installed: 5.9.0] ├── pexpect [required: &gt;4.3, installed: 4.8.0]
    │   └── ptyprocess [required: &gt;=0.5, installed: 0.7.0]
    ├── pickleshare [required: Any, installed: 0.7.5]
    ├── prompt-toolkit [required: &gt;=3.0.30,&lt;3.1.0,!=3.0.37, installed: 3.0.38] │ └── wcwidth [required: Any, installed: 0.2.6] ├── Pygments [required: &gt;=2.4.0, installed: 2.15.1]
    ├── stack-data [required: Any, installed: 0.6.2]
    │   ├── asttokens [required: &gt;=2.1.0, installed: 2.2.1]
    │   │   └── six [required: Any, installed: 1.16.0]
    │   ├── executing [required: &gt;=1.2.0, installed: 1.2.0]
    │   └── pure-eval [required: Any, installed: 0.2.2]
    └── traitlets [required: &gt;=5, installed: 5.9.0]
</pre>

<p>If you’re already using <a href="https://github.com/ipython/ipython">ipython</a>, this isn’t a problem because you’ll already need to download most of these dependencies anyway. But if you’re not using <code class="notranslate">ipython</code>… you’ll still need to download those dependencies.</p>

<p>Up next, is the <code class="notranslate">pdbpp</code> debugger. It has tab completion, syntax highlighting, better exceptions, different modes for displaying code so that you can get a full view vs. line-by-line, etc. Here’s a sample of how it looks:</p>

![pdbpp debugger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6na3zaxetf7o5ddk9rv5.png)

<figcaption id="caption-attachment-393" class="wp-caption-text">pdbpp debugger</figcaption></figure>

<p>Here’s what the main issue is: <code class="notranslate">pdbpp</code> has a dependency on <code class="notranslate">fancycompleter</code>, which has a Windows dependency on <code class="notranslate">pyreadline</code> (<a href="https://github.com/pyreadline/pyreadline">https://github.com/pyreadline/pyreadline</a>), which has this issue: <a class="issue-link js-issue-link" href="https://github.com/pyreadline/pyreadline/issues/65" data-error-text="Failed to load title" data-id="690591486" data-permission-text="Title is private" data-url="https://github.com/pyreadline/pyreadline/issues/65" data-hovercard-type="issue" data-hovercard-url="/pyreadline/pyreadline/issues/65/hovercard">pyreadline/pyreadline#65</a>, which leads to this error: <code class="notranslate">AttributeError: module 'collections' has no attribute 'Callable'</code>. This is a major problem for Windows users running Python <code class="notranslate">3.11</code> or newer.</p><div />

<h3 dir="auto">Here’s what I did to fix and improve on that: (Using <code class="notranslate">pdbp</code>)</h3>
<p dir="auto">I created the <strong><a class="notranslate" href="https://github.com/mdmintz/pdbp">pdbp</a> (Pdb+)</strong> Python debugger with a dependency on my own library <code class="notranslate">tabcompleter</code> (<a href="https://github.com/mdmintz/tabcompleter">https://github.com/mdmintz/tabcompleter</a>), which has a dependency on the improved <code class="notranslate">pyreadline3</code> (<a href="https://github.com/pyreadline3/pyreadline3/">https://github.com/pyreadline3/pyreadline3/</a>) instead of <code class="notranslate">pyreadline</code>. Then things started working again. As a bonus, I fixed some bugs, improved on default configuration settings, and added some new features.</p>

<h4 dir="auto">Not only is it powerful, but it’s light on dependencies. Here’s a <a href="https://github.com/tox-dev/pipdeptree">pipdeptree</a> for <code class="notranslate">pdbp</code>:</h4>
<pre class="notranslate">&gt; pipdeptree
pdbp==1.4.6
├── Pygments [required: &gt;=2.16.1, installed: 2.16.1]
└── tabcompleter [required: &gt;=1.2.1, installed: 1.2.1]
</pre>
<h3 dir="auto">Here are a few examples of the new <a href="https://github.com/mdmintz/pdbp">pdbp</a> debugger in action:</h3>

![pdbp (Pdb+) Python debugger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/47p160t5mdplyz73kw2m.png)

![pdbp (Pdb+) Python debugger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7sr54kl0hpfqyx5qjjor.png)

![pdbp (Pdb+) Python debugger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y5vqva6zhvt7wg7f5wmm.png)

![pdbp (Pdb+) Python debugger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qrckvbfgtfeksl52dqr.png)

<h3>Now that we’ve covered the differences between debuggers, let’s cover installation:</h3>
<p><code class="notranslate">pip install pdbp</code> (Note: <code class="notranslate">pdbp</code> is already included with <code class="notranslate">seleniumbase</code>)</p>
<p>Then add <code class="notranslate">import pdbp</code> to an <code class="notranslate">__init__.py</code> of your project, which will automatically make <code class="notranslate">Pdb+</code> the default debugger at breakpoints.</p>
<p>Now let’s talk about using it:</p>
<h3>Debug Mode in <code>pytest</code> can be triggered in a few different ways:</h3>
<ul>
<li>Your test raises an exception after passing the <code class="notranslate">"--pdb"</code> option to <code class="notranslate">"pytest"</code>.</li>
<li>The moment your test begins after passing the <code class="notranslate">"--trace"</code> option to <code class="notranslate">"pytest"</code>.</li>
<li>Calling <code class="notranslate">"pdb.set_trace()"</code> or <code class="notranslate">"pdbp.set_trace()"</code> from your test after importing <code class="notranslate">"pdb"</code> or <code class="notranslate">"pdbp"</code> respectively. (Calling the <code class="notranslate">"breakpoint()"</code> method also works.)</li>
<li>At the end of a test if you added the  <code class="notranslate">"--final-debug"</code> or <code class="notranslate">"--ftrace"</code> options to <code class="notranslate">"pytest"</code>. (<code class="notranslate">SeleniumBase</code>-only)</li>
</ul>
<p>When Debug Mode is activated, the browser window will remain open (when used in combination with browser automation), and you can see how variables look from the command-line.</p>
<p><b>(Note that you may need to add <code class="notranslate">"-s"</code> to your <code class="notranslate">"pytest"</code> run command to allow breakpoints, unless you already have a <code class="notranslate">"pytest.ini"</code> file present with <code class="notranslate">"addops = --capture=no"</code> in it.)</b></p>
<h3>Once you’re in Debug Mode, there are several commands that you can use in order to control and debug tests:</h3>
<ul>
<li><code class="notranslate">n (next)</code>: Execute the next line of the current method block.</li>
<li><code class="notranslate">s (step)</code>: Step through and execute the next line of the current method block (but if the current method calls another method, go down the stack).</li>
<li><code class="notranslate">c (continue)</code>: Leave Debug Mode and continue the test where the current method left off.</li>
<li><code class="notranslate">r (return)</code>: Continue running the test until the current method returns.</li>
<li><code class="notranslate">j (jump)</code>: Jump to the line number of the current method block.</li>
<li><code class="notranslate">w (where)</code>: Show where you are within the current stack trace.</li>
<li><code class="notranslate">u (up)</code>: Move up the stack.</li>
<li><code class="notranslate">d (down)</code>: Move down the stack.</li>
<li><code class="notranslate">ll (longlist)</code>: See the code for the current method block.</li>
<li><code class="notranslate">dir()</code>: List namespace objects.</li>
<li><code class="notranslate">h (help)</code>: List all available commands.</li>
</ul>
<h3>Here are some new commands added by <code class="notranslate">pdbp</code>:</h3>
<ul>
<li><code class="notranslate">sticky</code>: Toggle between sticky and non-sticky mode, which shows full code blocks vs individual lines in a stack.</li>
<li><code class="notranslate">trun (truncate)</code>: Use this to toggle between truncating or not truncating long lines in sticky mode.</li>
</ul>
<p>Additionally, you can execute any Python code that you want from within Debug Mode. (Assuming your code can be run in a single line.)</p>

<p>Now that you’ve covered the basics on using <code class="notranslate">pdbp</code>, see the <a href="https://github.com/mdmintz/pdbp">pdbp GitHub ReadMe</a> for more details.</p>

<p>And for Python browser automation, see the <a href="https://github.com/seleniumbase/SeleniumBase">SeleniumBase GitHub page</a>!</p>