Advanced python CoP - debugging any python code anywhere with pdb

In [2]:
%%HTML
<blockquote class="reddit-card" data-card-created="1587923907"><a href="https://www.reddit.com/r/ProgrammerHumor/comments/g0o1x3/the_holy_print_statement/">The holy print statement</a> from <a href="http://www.reddit.com/r/ProgrammerHumor">r/ProgrammerHumor</a></blockquote>
<script async src="//embed.redditmedia.com/widgets/platform.js" charset="UTF-8"></script>

How to start debugging?

  • from the shell python -m pdb <filename_or_modulename>
  • from the code import pdb; pdb.settrace()
  • from the code for python 3.7+ breakpoint()

You can disable all breakpoint calls with env variable: PYTHONBREAKPOINT=0
or use another debugger with PYTHONBREAKPOINT=ipdb.set_trace

Shell trick when the python script is in PATH

python -m pdb $(which apt) update

Behave captures stdout, so you won't see pdb output, but there's a simple fix: --no-capture

I could do a demo in ipython, but the callstack is a little cluttered and scrolling doesn't work well, so let's start the live demo in terminal.

Essential pdb commands

  • h(elp) -> print help
  • h(elp) <command> -> print help for specific command
  • l(ist) -> print current context
  • w(here) -> print call stack
  • s(tep) -> step into
  • n(ext) -> next line
  • b(reak) -> put a breakpoint
  • u(p) -> go up the callstack
  • d(own) -> go down the callstack

Extra: how to install pip package in docker image without rebuilding

  • run the image
  • if you're not root, attach new console as root: docker exec -it -u 0 987dc2a426ff bash
  • pip install pudb
  • commit the container: docker commit 987dc2a426ff swdl/aosp:latest

There are a lot of pdb flavours:

  • ipdb -> pdb with ipython shell
  • pudb -> ncurses version
In [13]:
%%HTML 
<img src="https://warehouse-camo.ingress.cmh1.psfhosted.org/d45b1912ee7774c2d0f86abff0815d631290243b/68747470733a2f2f74696b65722e6e65742f7075622f707564622d73637265656e73686f742e706e67
">

web_db -> browser debugger

In [1]:
%%HTML
<img src="https://warehouse-camo.ingress.cmh1.psfhosted.org/314b80b2f939bb4289633ad6a9c307a7147be20e/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f726f6d616e766d2f707974686f6e2d7765622d7064622f6d61737465722f73637265656e73686f742e706e67">

remote-pdb <- for really pdb-hostile environments, like no TTY

import rpdb; rpdb.set_trace()

$ nc 127.0.0.1 4444

django-pdb

pytest

pytest --pdb <- lands in pdb on test failure

Best practice

  • most of the time you're probably better off with your IDE/editor debugger
  • use something pdb-ish when
    • it's hard/impossible to integrate IDE/editor debugger or integration is not worth the effort
    • your editor can't debug python code