
Debugging Python Like a Boss - brian_cooksey
https://zapier.com/engineering/debugging-python-boss
======
haberman
Debuggers are cool and often necessary, but I disagree with this often-
expressed sentiment that print-debugging is a primitive hack for people who
don't know any better.

Debugging is determining the point at which the program's _expected_ behavior
diverges from its _actual_ behavior. You often don't know where where/when
this is happening. Print-debugging can give you a transcript of the program's
execution, which you can look at to hone in on the moment where things go
wrong. Stepping through a program's execution line-by-line and checking your
assumptions can be a lot slower in some cases. And most debuggers can't go
backwards, so if you miss the critical moment you have to start all over
again.

These are two tools in the toolbox; using print debugging does not mean you
are not "a boss."

~~~
ufo
One neat trick that I really like for ptrintf debugging is using conditional
breakpoints and putting the call to the printing function inside the
breakpoint condition. This lets you add print statements without editing the
original code and makes it very easy to toggle them on and off.

~~~
masklinn
Some IDEs have support for doing that without the hack. Xcode for instance,
when you set a breakpoint you can edit it to not break, and execute custom
actions (logging stuff, executing debugger commands, executing a shell script,
executing actionscript, playing a sound).

A condition, if set, will then apply to whether the action should or should
not be applied.

The great part is they can all be combined, so you can setup a breakpoint
which will pre-log the info you know you'll need then drop you in the visual
debugger with all base information waiting for you.

------
hcarvalhoalves
A good list of libraries, but please, don't use this in the middle of your
code to set a break point:

    
    
        import pdb; pdb.set_trace();
    

There's a chance you forget this, check-in, and it ends in production. Use pdb
facilities instead:

    
    
        $ python -m pdb <myscript>
    

Then set a breakpoint and continue:

    
    
        (Pdb) break <filename.py>:<line>
        (Pdb) c
    

This is trivial to automate from any editor or command line, so you don't even
have to guess the path to the file.

EDIT: For the lazy, here's a script to set breakpoints from the command line
and run your scripts:

[https://gist.github.com/hcarvalhoalves/7587621](https://gist.github.com/hcarvalhoalves/7587621)

~~~
codygman
How would I do that with something like django?

~~~
Newky
You are right that this is not straight forward in Django.

There are a number of different routes in Django development that you may need
to debug:

1\. Debugging view endpoints when not using runserver (for example when
testing out your actual deploy webserver). For this, none the debuggers will
work, as you have no console to run through. I combat this by using winpdb
that allows remote debugging.

2\. Debugging either unittest based code or when using runserver, you can use
the method described by hcarvalhoalves comment.

However, I still think that in lots of cases its more powerful to import in
the code. With the necessary coverage in tests, it should always be picked up.

~~~
codygman

        $ python -m pdb manage.py test
            (Pdb) break mymodule/myfile.py:42
            (Pdb) c
    

The above should work for tests if I understand correctly, though I haven't
checked yet. This solves most of my current debugging problems, and if I'm
reading correctly that would solve yours too?

I wonder if you could also use it with runfcgi or any of the other manage
commands? I personally use nginx+gunicorn, but for testing production I could
switch it to runfcgi or similar really quick.

To be honest though, I don't find myself ever debugging production.

------
rtpg
The most frustrating thing (experienced in both Javascript and Python) is the
"oh uncaught exception? let me just quit everything" model. Most of the time,
if I were just given an interactive prompt right then, I could spend 1 minute
looking at local variables, maybe get a special stack trace variable to look
at that, then be over with it.

Instead I have to stick in some print statements and start everything over
again.

~~~
davmre
There's a nice trick to enable this behavior for standard Python code run at
the command line. Write the body of your code inside a main() function, then
call it using the following toplevel block:

    
    
      if __name__ == "__main__":
          try:
              main()
          except KeyboardInterrupt: # allow ctrl-C
              raise
          except Exception as e:
              import sys, traceback, pdb
              print e
              type, value, tb = sys.exc_info()
              traceback.print_exc()
              pdb.post_mortem(tb)
    

This will catch any exceptions and throw you into PDB in the context where the
exception was raised. You probably don't want to leave it in production code,
but it's super useful for development.

~~~
ekimekim
Minor gripe, the except KeyboardInterrupt isn't necessary, since
KeyboardInterrupt is a BaseException, not an Exception.

~~~
btbuilder
Only since Python 2.5 I believe.

------
edwinnathaniel
I've been using Python for a while for fun and Ruby (Rails) on and off.

I've always find it interesting how the Python/Ruby community debug your code
both during development (coding or writing unit-tests) and perhaps in
production as well (for the record, I use "print" as my debugging tool).

I'm a long time Eclipse user who has recently converted to IntelliJ (almost a
year) and the debugger that comes with these editors is something I can't live
without hence I have not moved to Emacs or VI(m) or whatever the UNIX hackers
use because it would crippled my productivity significantly (or so I thought,
feel free to criticize my point of view).

So sometimes I'm wondering how productive Python/Ruby + VIM/Emacs users. Just
an honest question really.

PS: most Java IDE debuggers can do local AND remote AND has some support for
hotswap code.

~~~
gknoy
I've used "println debugging" more than I have used an IDE's debugger, and am
more comfortable with the former. I think it revolves around a different way
of using them, and is likely very heavily influenced by having spent a lot of
time developing with a REPL handy.

When I did mostly Java coding, I would tend to use println debugging rather
than dive into the IDE's debugger, as I tended to be able to zero in more
easily on what was going on when I took a holistic "Let's print out each
item's id and name ..." approach to start.

Now that I do most of my code in Python, I use the interactive debugger almost
exclusively.

With an IDE, I can look at variables' contents. What do I do when I want to
check the result of a method call, though? It is likely tool unfamiliarity,
but it's never been clear how to check that as something to inspect. (If you
know how to do this, then you're a much more savvy user of the IDE's debugging
tools than I am.) If I don't have the right breakpoint, or the right
questions, I often glean little.

Println debugging is an easy way to see that you're looping incorrectly, or
that All Your Data is bad in a way you didn't expect.

With a REPL-style debugger, I can treat it as an interactive question/answer
session that lets me check things like contents of the database, or the values
that helper methods return:

    
    
      > print len(foo.items)
      0
      # why??? Maybe the objects don't exist?
      > print Foo.objects.filter(bar=42)
      [foo1, foo2, foo3]
      # Let me place a new breakpoint then in 
      # my JsFoo.from_db_item() method, and try again ....
    

I think the nicest thing about an interactive debugger is that it lets me
construct arbitrary expressions -- print lists of things, look at nested data,
etc -- in the language I am already developing in. I always had a hard time
doing something quite as powerful in Eclipse.

~~~
edwinnathaniel
I used to do "println" debugging trick during my early days of programming
until more senior people around me slap my hand and told me to use the
debugger efficiently and effectively.

In Eclipse/IntelliJ you can set "Conditional Breakpoint" (only stop/break when
certain conditions is met) very handy when debugging a loop. In addition to
that, you can also set "breakpoint on any Exception".

Also, in Eclipse/IntelliJ, when the debugger hits the breakpoint, you could
execute Java code within the context of that breakpoint (of course, java.lang
is given by default in addition to the context of that breakpoint).

I've never done more complex debugging than that but I'm guessing you can
write almost anything you want within the "evaluate window" in those IDEs.

------
freakboy3742
One feature that all these tools share is that they're console based. This is
nice, but there's a reason we all use graphical environments for our daily
computing -- rich graphical user interfaces are a powerful tool for
visualising complex data. However, you don't have to adopt a full IDE to get a
graphical UI. Bugjar ([http://pybee.org/bugjar](http://pybee.org/bugjar)) is a
graphical debugger -- not an IDE, just a debugger. It uses Tkinter, so it's
cross platform, and can be installed using "pip install bugjar".

It's an early stage project, but hopefully demonstrates that there is a middle
ground between "Everything in an 80x25 text window" and "500lb IDE gorilla".

(Full disclosure: I'm the core developer of Bugjar)

------
smortaz
very nice! plug: if you happen to be on windows, try PTVS which has nice
features like mixed-mode Python/C++ debugging as well cross debugging from
Visual Studio <-> linux & MacOS. (it's a free plug-in).

[http://www.youtube.com/watch?v=wvJaKQ94lBY](http://www.youtube.com/watch?v=wvJaKQ94lBY)

~~~
corysama
Although VStudio Express does not support plugins, you can also use PTVS in
combination with the free "VS2013 Shell"
[https://pytools.codeplex.com/wikipage?title=PTVS%20Installat...](https://pytools.codeplex.com/wikipage?title=PTVS%20Installation)

------
makmanalp
Most notably, pydbgr has out of process debugging, so you can attach to a
server process and diagnose a deadlock, for example.

~~~
zmmmmm
Thanks! this is what I miss most from debugging on the JVM stack. I am rarely
in control of / responsible for starting the processes I want to debug. The
JVM's ability to simply attach and set a breakpoint to jump in in real time,
even on a remote server, when something is going wrong is a complete
lifesaver.

------
siliconc0w
What is also useful are the various web framework's support for debugging in
realtime. If you haven't worked on a web application that lets you just type
code in when it throws a 500 I highly recommend it.

Also what I like to do with ipdb is set a debug point and just write new
functionality in real time. Most good programmers probably do this in their
heads but having a computer do it for you is the next best thing. You catch
bugs almost immediately (hey this variable isn't supposed to be empty!). It
feels pretty cool to send a request to a web app and just pound out the code
to make it respond correctly before the browser gives up on the HTTP
connection.

------
dmd
One thing I love about much-maligned Tcl is its ability to connect a repl to a
_running_ program.

Not just remote debugging of a halted program - you can actually inspect and
alter variables and issue commands into the executing code.

Is there a way to do that in, say, Python?

~~~
hcarvalhoalves
All Python debuggers allow you to execute statements, on top of navigating the
stack.

~~~
dmd
Python debuggers, as far as I know, require the program to be in a halted
state - i.e., you're stepping through it.

In Tcl, the program can be running its event loop at normal speed, and you can
inject commands into that event loop while it runs.

------
defrex
This article is missing pdb++[1], which I would argue is much less buggy then
ipdb while having essentially all the same features.

[1] [https://pypi.python.org/pypi/pdbpp/](https://pypi.python.org/pypi/pdbpp/)

~~~
brian_cooksey
Thanks for the link. It wasn't one that came up when I was searching, but it
definitely looks like another solid option. Sticky mode in particular sounds
slick.

------
memracom
Print debugging is faster. Most people who use this technique also don't make
so many mistakes because they take the time to review their code, not to
mention writing unit tests.

Their debug cycle is a) notice something is not quite right. b) insert some
print statements in the code that they just changed. c) run it again. d) look
at the code and the print statements to see where they made a wrong
assumption, fix it and move on.

No need for figuring out where to set a break or single stepping through too
much tangle.

------
benzesandbetter
Really... so using a debugger, um that's pretty pro-level.

I thought there would actually be some innovative techniques in this article.

Perhaps a better title would be, "A review of python debuggers".

------
softworks
TDD + print() == "debugging like a BOSS". :)

In all honesty I rarely feel the need for anything more. Generally I don't
even need the print() because I stick to small self contained functions.

The exception is when I'm using a poorly documented or new to me open source
library. I guess at times like that a debugger may be useful. So next time I
run into such a situation I'll try out a debugger.

But I can't see much of a reason for it in my own code.

------
cbarion
Here's another library to help debugging:
[https://pypi.python.org/pypi/globexc](https://pypi.python.org/pypi/globexc).
It tells the Python interpreter to write a detailed trace file (including
contents of variables) if there is an unhandled exception. It's less powerful
than a proper debugger but the trace file is always there after a crash which
can be very convenient.

------
gbog
I would say that the real boss debugging starts with finding a way to make it
first a unittest debugging.

Once the weird behavior is covered, usually print debugging is even better
than pdb because it will encourage you to extend the test suite.

What I would like though is a special monkey patching in python that allow my
to write print like "p this that" and will prettyprint this and that on stdout

------
ruxkor
A very nice list of debuggers, but I'm wondering why there is no mentioning of
the (very good) debugging support you can find in IntelliJ and Eclipse and
mostly, why there is no mentioning of Winpdb [1]; a very nice and platform-
independent Python debugger with a full-fledged GUI.

[1]: [http://winpdb.org/](http://winpdb.org/)

~~~
brian_cooksey
Mostly because I'm a VIM + command line type of guy :)

I'm aware there are a slew of plugins/built-ins with IDE's that I didn't
cover. As I mentioned in a comment on the post, I think a disclaimer that
stated my preference would have helped.

------
roycehaynes
First off, great post Cooksey. I'm actually a sublime and pycharm type of guy,
where I use pycharm mostly for debugging purposes. I use pdb only if I'm
debugging on a machine thats not mine, I need to debug something fairly
quickly, or PyCharm isn't available. I definitely need to give ipdb a try.

~~~
brian_cooksey
Thanks, and long time no see. Hope things are going well for ya!

I'm interested in the number of people that do the Editor-of-Choice and
PyCharm combo. May have to see how the GVIM PyCharm combo would work.

------
est
remote debugging with pdb+socket

1\. first listen to a socket with nc -l -U 1.sock

2\. Add this to your python script.

    
    
        import socket, pdb
    
        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.connect('1.sock')
        f = s.makefile()
        pdb.Pdb(stdin=f, stdout=f).set_trace()
    
        raise wtf
    
    

3\. now debug in nc. enjoy.

------
rbanffy
Interestingly, it's a dupe:

[https://news.ycombinator.com/item?id=6770412](https://news.ycombinator.com/item?id=6770412)

But I'm happy. When I posted, it failed to generate a discussion. If it were
identified as a dupe this time, it would probably be forgotten.

It's a great article.

------
jamtan
I use epdb because of it's ability to open a raw socket at a breakpoint with
epdb.serve()

[https://bitbucket.org/rpathsync/epdb](https://bitbucket.org/rpathsync/epdb)

------
mcpherson
While in the subject of debugging Python you should look into Bugjar (gui)
[http://pybee.org/bugjar/](http://pybee.org/bugjar/).

Looks really good.

~~~
emidln
I see pdb++[1] getting mentioned (pip instal pdbpp), and I'll also throw in
wdb[2], which is a WSGI middleware that uses jedi for code introspection.

[1] -
[https://bitbucket.org/antocuni/pdb/src](https://bitbucket.org/antocuni/pdb/src)

[2] - [https://github.com/Kozea/wdb](https://github.com/Kozea/wdb)

------
bonemachine
_TL;DR_ , basically boiling down to:

"There are debugger people, and then there are printf people, you see..."

~~~
catnaroek
And there are people who only write code after they have figured out why their
design is right.

~~~
themstheones
I've never met one.

------
keypusher
Does anyone know of good remote debugging tool or even a way to attach to a
running local python process and get into the breaks? We have automated
testing in python, and it is kicked off via a daemon, so executing the scripts
by hand can be a pain.

~~~
chris_mahan
I run an xmlrpc server, then have the jobs log to the server while they are
running. Then I just look at the server logs as they come in (they're files,
so tail works fine)

This works across the internet.

