How to debug in Django, the good way? [closed]

How to debug in Django, the good way? [closed]






Closed. This question needs to be more focused. It is not currently accepting answers.
                            
                        










Want to improve this question? Update the question so it focuses on one problem only by editing this post.
                        
Closed 2 years ago.



So, I started learning to code in Python and later Django. The first times it was hard looking at tracebacks and actually figure out what I did wrong and where the syntax error was. Some time has passed now and some way along the way, I guess I got a routine in debugging my Django code. As this was done early in my coding experience, I sat down and wondered if how I was doing this was ineffective and could be done faster. I usually manage to find and correct the bugs in my code, but I wonder if I should be doing it faster?
I usually just use the debug info Django gives when enabled. When things do end up as I thought it would, I break the code flow a lot with a syntax error, and look at the variables at that point in the flow to figure out, where the code does something other than what I wanted.
But can this be improved? Are there some good tools or better ways to debug your Django code?

Solutions/Answers:

Answer 1:

There are a bunch of ways to do it, but the most straightforward is to simply
use the Python debugger. Just add following line in to a Django view function:

import pdb; pdb.set_trace()

or

breakpoint()  #from Python3.7

If you try to load that page in your browser, the browser will hang and you get a prompt to carry on debugging on actual executing code.

However there are other options (I am not recommending them):

* return HttpResponse({variable to inspect})

* print {variable to inspect}

* raise Exception({variable to inspect})

But the Python Debugger (pdb) is highly recommended for all types of Python code. If you are already into pdb, you’d also want to have a look at IPDB that uses ipython for debugging.

Some more useful extension to pdb are

pdb++, suggested by Antash.

pudb, suggested by PatDuJour.

Using the Python debugger in Django, suggested by Seafangs.

Answer 2:

I really like Werkzeug‘s interactive debugger. It’s similar to Django’s debug page, except that you get an interactive shell on every level of the traceback. If you use the django-extensions, you get a runserver_plus managment command which starts the development server and gives you Werkzeug’s debugger on exceptions.

Of course, you should only run this locally, as it gives anyone with a browser the rights to execute arbitrary python code in the context of the server.

Answer 3:

A little quickie for template tags:

@register.filter 
def pdb(element):
    import pdb; pdb.set_trace()
    return element

Now, inside a template you can do {{ template_var|pdb }} and enter a pdb session (given you’re running the local devel server) where you can inspect element to your heart’s content.

It’s a very nice way to see what’s happened to your object when it arrives at the template.

Answer 4:

There are a few tools that cooperate well and can make your debugging task easier.

Most important is the Django debug toolbar.

Then you need good logging using the Python logging facility. You can send logging output to a log file, but an easier option is sending log output to firepython. To use this you need to use the Firefox browser with the firebug extension. Firepython includes a firebug plugin that will display any server-side logging in a Firebug tab.

Firebug itself is also critical for debugging the Javascript side of any app you develop. (Assuming you have some JS code of course).

I also liked django-viewtools for debugging views interactively using pdb, but I don’t use it that much.

There are more useful tools like dozer for tracking down memory leaks (there are also other good suggestions given in answers here on SO for memory tracking).

Answer 5:

I use PyCharm (same pydev engine as eclipse). Really helps me to visually be able to step through my code and see what is happening.

Answer 6:

Almost everything has been mentioned so far, so I’ll only add that instead of pdb.set_trace() one can use ipdb.set_trace() which uses iPython and therefore is more powerful (autocomplete and other goodies). This requires ipdb package, so you only need to pip install ipdb

Answer 7:

I’ve pushed django-pdb to PyPI.
It’s a simple app that means you don’t need to edit your source code every time you want to break into pdb.

Installation is just…

  1. pip install django-pdb
  2. Add 'django_pdb' to your INSTALLED_APPS

You can now run: manage.py runserver --pdb to break into pdb at the start of every view…

bash: manage.py runserver --pdb
Validating models...

0 errors found
Django version 1.3, using settings 'testproject.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

GET /
function "myview" in testapp/views.py:6
args: ()
kwargs: {}

> /Users/tom/github/django-pdb/testproject/testapp/views.py(7)myview()
-> a = 1
(Pdb)

And run: manage.py test --pdb to break into pdb on test failures/errors…

bash: manage.py test testapp --pdb
Creating test database for alias 'default'...
E
======================================================================
>>> test_error (testapp.tests.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../django-pdb/testproject/testapp/tests.py", line 16, in test_error
    one_plus_one = four
NameError: global name 'four' is not defined
======================================================================

> /Users/tom/github/django-pdb/testproject/testapp/tests.py(16)test_error()
-> one_plus_one = four
(Pdb)

The project’s hosted on GitHub, contributions are welcome of course.

Answer 8:

The easiest way to debug python – especially for programmers that are used to Visual Studio – is using PTVS (Python Tools for Visual Studio).
The steps are simple:

  1. Download and install it from http://pytools.codeplex.com/
  2. Set breakpoints and press F5.
  3. Your breakpoint is hit, you can view/change the variables as easy as debugging C#/C++ programs.
  4. That’s all 🙂

If you want to debug Django using PTVS, you need to do the following:

  1. In Project settings – General tab, set “Startup File” to “manage.py”, the entry point of the Django program.
  2. In Project settings – Debug tab, set “Script Arguments” to “runserver –noreload”. The key point is the “–noreload” here. If you don’t set it, your breakpoints won’t be hit.
  3. Enjoy it.

Answer 9:

I use pyDev with Eclipse really good, set break points, step into code, view values on any objects and variables, try it.

Answer 10:

I use PyCharm and stand by it all the way. It cost me a little but I have to say the advantage that I get out of it is priceless. I tried debugging from console and I do give people a lot of credit who can do that, but for me being able to visually debug my application(s) is great.

I have to say though, PyCharm does take a lot of memory. But then again, nothing good is free in life. They just came with their latest version 3. It also plays very well with Django, Flask and Google AppEngine. So, all in all, I’d say it’s a great handy tool to have for any developer.

If you are not using it yet, I’d recommend to get the trial version for 30 days to take a look at the power of PyCharm. I’m sure there are other tools also available, such as Aptana. But I guess I just also like the way PyCharm looks. I feel very comfortable debugging my apps there.

Answer 11:

Sometimes when I wan to explore around in a particular method and summoning pdb is just too cumbersome, I would add:

import IPython; IPython.embed()

IPython.embed() starts an IPython shell which have access to the local variables from the point where you call it.

Answer 12:

From my perspective, we could break down common code debugging tasks into three distinct usage patterns:

  1. Something has raised an exception: runserver_plus‘ Werkzeug debugger to the rescue. The ability to run custom code at all the trace levels is a killer. And if you’re completely stuck, you can create a Gist to share with just a click.
  2. Page is rendered, but the result is wrong: again, Werkzeug rocks. To make a breakpoint in code, just type assert False in the place you want to stop at.
  3. Code works wrong, but the quick look doesn’t help. Most probably, an algorithmic problem. Sigh. Then I usually fire up a console debugger PuDB: import pudb; pudb.set_trace(). The main advantage over [i]pdb is that PuDB (while looking as you’re in 80’s) makes setting custom watch expressions a breeze. And debugging a bunch of nested loops is much simpler with a GUI.

Ah, yes, the templates’ woes. The most common (to me and my colleagues) problem is a wrong context: either you don’t have a variable, or your variable doesn’t have some attribute. If you’re using debug toolbar, just inspect the context at the “Templates” section, or, if it’s not sufficient, set a break in your views’ code just after your context is filled up.

So it goes.

Answer 13:

I highly recommend epdb (Extended Python Debugger).

https://bitbucket.org/dugan/epdb

One thing I love about epdb for debugging Django or other Python webservers is the epdb.serve() command. This sets a trace and serves this on a local port that you can connect to. Typical use case:

I have a view that I want to go through step-by-step. I’ll insert the following at the point I want to set the trace.

import epdb; epdb.serve()

Once this code gets executed, I open a Python interpreter and connect to the serving instance. I can analyze all the values and step through the code using the standard pdb commands like n, s, etc.

In [2]: import epdb; epdb.connect()
(Epdb) request
<WSGIRequest
path:/foo,
GET:<QueryDict: {}>, 
POST:<QuestDict: {}>,
...
>
(Epdb) request.session.session_key
'i31kq7lljj3up5v7hbw9cff0rga2vlq5'
(Epdb) list
 85         raise some_error.CustomError()
 86 
 87     # Example login view
 88     def login(request, username, password):
 89         import epdb; epdb.serve()
 90  ->     return my_login_method(username, password)
 91
 92     # Example view to show session key
 93     def get_session_key(request):
 94         return request.session.session_key
 95

And tons more that you can learn about typing epdb help at any time.

If you want to serve or connect to multiple epdb instances at the same time, you can specify the port to listen on (default is 8080). I.e.

import epdb; epdb.serve(4242)

>> import epdb; epdb.connect(host='192.168.3.2', port=4242)

host defaults to ‘localhost’ if not specified. I threw it in here to demonstrate how you can use this to debug something other than a local instance, like a development server on your local LAN. Obviously, if you do this be careful that the set trace never makes it onto your production server!

As a quick note, you can still do the same thing as the accepted answer with epdb (import epdb; epdb.set_trace()) but I wanted to highlight the serve functionality since I’ve found it so useful.

Answer 14:

I just found wdb (http://www.rkblog.rk.edu.pl/w/p/debugging-python-code-browser-wdb-debugger/?goback=%2Egde_25827_member_255996401). It has a pretty nice user interface / GUI with all the bells and whistles. Author says this about wdb –

“There are IDEs like PyCharm that have their own debuggers. They offer similar or equal set of features … However to use them you have to use those specific IDEs (and some of then are non-free or may not be available for all platforms). Pick the right tool for your needs.”

Thought i’d just pass it on.

Also a very helpful article about python debuggers:
https://zapier.com/engineering/debugging-python-boss/

Finally, if you’d like to see a nice graphical printout of your call stack in Django, checkout:
https://github.com/joerick/pyinstrument. Just add pyinstrument.middleware.ProfilerMiddleware to MIDDLEWARE_CLASSES, then add ?profile to the end of the request URL to activate the profiler.

Can also run pyinstrument from command line or by importing as a module.

References