I started out trying to pick through the interesting features in Python 3.7 but ended up leaving it so long that Python 3.8 is already out. Even so, there’s a feature that I genuinely only noticed a week ago, and it’s a small but significant one.
For as long as I’ve known how to write Python my standard tool when I’m frustrated with a unit test is to insert on the offending line:
import pdb; pdb.set_trace()
I never got used to managing breakpoints in my IDE because I’m often running something remotely or in a docker container and remote debugging is usually a pain to set up.
Still, it’s always bugged me that this has to be two lines of code.
Luckily someone else has had the same thoughts as me, and more to the point has got round to doing something about it. From Python 3.7 onwards, there’s a built-in function that allows you to do this in one line:
And that’s all there is to it.
Digging a bit deeper
It turns out that the code:
does a little more than the old PDB snippet above, as the documentation helpfully explains:
This function drops you into the debugger at the call site. Specifically, it calls
kwsstraight through. By default,
pdb.set_trace()expecting no arguments. In this case, it is purely a convenience function so you don’t have to explicitly import
pdbor type as much code to enter the debugger. However,
sys.breakpointhook()can be set to some other function and
breakpoint()will automatically call that, allowing you to drop into the debugger of choice.
sys.breakpointhook is made available as a writable value, and you can assign your own choice of function over it. This isn’t very useful as a developer, but it’s vital if you’re an IDE writer. When you run Python in an IDE, you might want to provide your own suite of debug tools without PDB getting in the way. If someone’s using your IDE to debug their code and they type
breakpoint(), they probably want the IDE breakpoint feature and not PDB.
This raises an interesting question of whether this could be used maliciously. Code could write to
sys.breakpointhook to make itself more difficult to debug, or it could check the value of it in order to exhibit different behaviour when run in a non-PDB debugger. This is pretty limited though, since anyone having trouble with an IDE debugger will probably fall back to trying PDB pretty quickly and defeat this simple trick.