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 4 years ago.
Improve this question
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?
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.
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.
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.
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).
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.
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
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...
pip install django-pdb
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.
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:
Download and install it from https://microsoft.github.io/PTVS/
Set breakpoints and press F5.
Your breakpoint is hit, you can view/change the variables as easy as debugging C#/C++ programs.
That's all :)
If you want to debug Django using PTVS, you need to do the following:
In Project settings - General tab, set "Startup File" to "manage.py", the entry point of the Django program.
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.
Enjoy it.
I use pyDev with Eclipse really good, set break points, step into code, view values on any objects and variables, try it.
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.
From my perspective, we could break down common code debugging tasks into three distinct usage patterns:
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.
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.
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.
Add import pdb; pdb.set_trace() or breakpoint() (form python3.7) at the corresponding line in the Python code and execute it. The execution will stop with an interactive shell. In the shell you can execute Python code (i.e. print variables) or use commands such as:
c continue execution
n step to the next line within the same function
s step to the next line in this function or a called function
q quit the debugger/execution
Also see: https://poweruser.blog/setting-a-breakpoint-in-python-438e23fe6b28
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.
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.
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.
One of your best option to debug Django code is via wdb:
https://github.com/Kozea/wdb
wdb works with python 2 (2.6, 2.7), python 3 (3.2, 3.3, 3.4, 3.5) and pypy. Even better, it is possible to debug a python 2 program with a wdb server running on python 3 and vice-versa or debug a program running on a computer with a debugging server running on another computer inside a web page on a third computer!
Even betterer, it is now possible to pause a currently running python process/thread using code injection from the web interface. (This requires gdb and ptrace enabled)
In other words it's a very enhanced version of pdb directly in your browser with nice features.
Install and run the server, and in your code add:
import wdb
wdb.set_trace()
According to the author, main differences with respect to pdb are:
For those who don’t know the project, wdb is a python debugger like pdb, but with a slick web front-end and a lot of additional features, such as:
Source syntax highlighting
Visual breakpoints
Interactive code completion using jedi
Persistent breakpoints
Deep objects inspection using mouse Multithreading / Multiprocessing support
Remote debugging
Watch expressions
In debugger code edition
Popular web servers integration to break on error
In exception breaking during trace (not post-mortem) in contrary to the werkzeug debugger for instance
Breaking in currently running programs through code injection (on supported systems)
It has a great browser-based user interface. A joy to use! :)
I use PyCharm and different debug tools. Also have a nice articles set about easy set up those things for novices. You may start here. It tells about PDB and GUI debugging in general with Django projects. Hope someone would benefit from them.
If using Aptana for django development, watch this: http://www.youtube.com/watch?v=qQh-UQFltJQ
If not, consider using it.
Most options are alredy mentioned.
To print template context, I've created a simple library for that.
See https://github.com/edoburu/django-debugtools
You can use it to print template context without any {% load %} construct:
{% print var %} prints variable
{% print %} prints all
It uses a customized pprint format to display the variables in a <pre> tag.
I find Visual Studio Code is awesome for debugging Django apps. The standard python launch.json parameters run python manage.py with the debugger attached, so you can set breakpoints and step through your code as you like.
For those that can accidentally add pdb into live commits, I can suggest this extension of #Koobz answer:
#register.filter
def pdb(element):
from django.conf import settings
if settings.DEBUG:
import pdb
pdb.set_trace()
return element
From my own experience , there are two way:
use ipdb,which is a enhanced debugger likes pdb.
import ipdb;ipdb.set_trace() or breakpoint() (from python3.7)
use django shell ,just use the command below. This is very helpfull when you are developing a new view.
python manage.py shell
i highly suggest to use PDB.
import pdb
pdb.set_trace()
You can inspect all the variables values, step in to the function and much more.
https://docs.python.org/2/library/pdb.html
for checking out the all kind of request,response and hits to database.i am using django-debug-toolbar
https://github.com/django-debug-toolbar/django-debug-toolbar
As mentioned in other posts here - setting breakpoints in your code and walking thru the code to see if it behaves as you expected is a great way to learn something like Django until you have a good sense of how it all behaves - and what your code is doing.
To do this I would recommend using WingIde. Just like other mentioned IDEs nice and easy to use, nice layout and also easy to set breakpoints evaluate / modify the stack etc. Perfect for visualizing what your code is doing as you step through it. I'm a big fan of it.
Also I use PyCharm - it has excellent static code analysis and can help sometimes spot problems before you realize they are there.
As mentioned already django-debug-toolbar is essential - https://github.com/django-debug-toolbar/django-debug-toolbar
And while not explicitly a debug or analysis tool - one of my favorites is SQL Printing Middleware available from Django Snippets at https://djangosnippets.org/snippets/290/
This will display the SQL queries that your view has generated. This will give you a good sense of what the ORM is doing and if your queries are efficient or you need to rework your code (or add caching).
I find it invaluable for keeping an eye on query performance while developing and debugging my application.
Just one other tip - I modified it slightly for my own use to only show the summary and not the SQL statement.... So I always use it while developing and testing. I also added that if the len(connection.queries) is greater than a pre-defined threshold it displays an extra warning.
Then if I spot something bad (from a performance or number of queries perspective) is happening I turn back on the full display of the SQL statements to see exactly what is going on. Very handy when you are working on a large Django project with multiple developers.
use pdb or ipdb. Diffrence between these two is ipdb supports auto complete.
for pdb
import pdb
pdb.set_trace()
for ipdb
import ipdb
ipdb.set_trace()
For executing new line hit n key, for continue hit c key.
check more options by using help(pdb)
An additional suggestion.
You can leverage nosetests and pdb together, rather injecting pdb.set_trace() in your views manually. The advantage is that you can observe error conditions when they first start, potentially in 3rd party code.
Here's an error for me today.
TypeError at /db/hcm91dmo/catalog/records/
render_option() argument after * must be a sequence, not int
....
Error during template rendering
In template /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/crispy_forms/templates/bootstrap3/field.html, error at line 28
render_option() argument after * must be a sequence, not int
18
19 {% if field|is_checkboxselectmultiple %}
20 {% include 'bootstrap3/layout/checkboxselectmultiple.html' %}
21 {% endif %}
22
23 {% if field|is_radioselect %}
24 {% include 'bootstrap3/layout/radioselect.html' %}
25 {% endif %}
26
27 {% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
28
{% if field|is_checkbox and form_show_labels %}
Now, I know this means that I goofed the constructor for the form, and I even have good idea of which field is a problem. But, can I use pdb to see what crispy forms is complaining about, within a template?
Yes, I can. Using the --pdb option on nosetests:
tests$ nosetests test_urls_catalog.py --pdb
As soon as I hit any exception (including ones handled gracefully), pdb stops where it happens and I can look around.
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/forms.py", line 537, in __str__
return self.as_widget()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/forms.py", line 593, in as_widget
return force_text(widget.render(name, self.value(), attrs=attrs))
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py", line 513, in render
options = self.render_options(choices, [value])
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py", line 543, in render_options
output.append(self.render_option(selected_choices, *option))
TypeError: render_option() argument after * must be a sequence, not int
INFO lib.capture_middleware log write_to_index(http://localhost:8082/db/hcm91dmo/catalog/records.html)
INFO lib.capture_middleware log write_to_index:end
> /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py(543)render_options()
-> output.append(self.render_option(selected_choices, *option))
(Pdb) import pprint
(Pdb) pprint.PrettyPrinter(indent=4).pprint(self)
<django.forms.widgets.Select object at 0x115fe7d10>
(Pdb) pprint.PrettyPrinter(indent=4).pprint(vars(self))
{ 'attrs': { 'class': 'select form-control'},
'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]],
'is_required': False}
(Pdb)
Now, it's clear that my choices argument to the crispy field constructor was as it was a list within a list, rather than a list/tuple of tuples.
'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]]
The neat thing is that this pdb is taking place within crispy's code, not mine and I didn't need to insert it manually.
During development, adding a quick
assert False, value
can help diagnose problems in views or anywhere else, without the need to use a debugger.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Closed 8 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What are your best tips for debugging Python?
Please don't just list a particular debugger without saying what it can actually do.
Related
What are good ways to make my Python code run first time? - This discusses minimizing errors
PDB
You can use the pdb module, insert pdb.set_trace() anywhere and it will function as a breakpoint.
>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)
To continue execution use c (or cont or continue).
It is possible to execute arbitrary Python expressions using pdb. For example, if you find a mistake, you can correct the code, then type a type expression to have the same effect in the running code
ipdb is a version of pdb for IPython. It allows the use of pdb with all the IPython features including tab completion.
It is also possible to set pdb to automatically run on an uncaught exception.
Pydb was written to be an enhanced version of Pdb. Benefits?
http://pypi.python.org/pypi/pudb, a full-screen, console-based Python debugger.
Its goal is to provide all the niceties of modern GUI-based debuggers in a more lightweight and keyboard-friendly package. PuDB allows you to debug code right where you write and test it – in a terminal. If you've worked with the excellent (but nowadays ancient) DOS-based Turbo Pascal or C tools, PuDB's UI might look familiar.
Nice for debugging standalone scripts, just run
python -m pudb.run my-script.py
If you are using pdb, you can define aliases for shortcuts. I use these:
# Ned's .pdbrc
# Print a dictionary, sorted. %1 is the dict, %2 is the prefix for the names.
alias p_ for k in sorted(%1.keys()): print "%s%-15s= %-80.80s" % ("%2",k,repr(%1[k]))
# Print the instance variables of a thing.
alias pi p_ %1.__dict__ %1.
# Print the instance variables of self.
alias ps pi self
# Print the locals.
alias pl p_ locals() local:
# Next and list, and step and list.
alias nl n;;l
alias sl s;;l
# Short cuts for walking up and down the stack
alias uu u;;u
alias uuu u;;u;;u
alias uuuu u;;u;;u;;u
alias uuuuu u;;u;;u;;u;;u
alias dd d;;d
alias ddd d;;d;;d
alias dddd d;;d;;d;;d
alias ddddd d;;d;;d;;d;;d
Logging
Python already has an excellent built-in logging module. You may want to use the logging template here.
The logging module lets you specify a level of importance; during debugging you can log everything, while during normal operation you might only log critical things. You can switch things off and on.
Most people just use basic print statements to debug, and then remove the print statements. It's better to leave them in, but disable them; then, when you have another bug, you can just re-enable everything and look your logs over.
This can be the best possible way to debug programs that need to do things quickly, such as networking programs that need to respond before the other end of the network connection times out and goes away. You might not have much time to single-step a debugger; but you can just let your code run, and log everything, then pore over the logs and figure out what's really happening.
EDIT: The original URL for the templates was: http://aymanh.com/python-debugging-techniques
This page is missing so I replaced it with a reference to the snapshot saved at archive.org: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-techniques
In case it disappears again, here are the templates I mentioned. This is code taken from the blog; I didn't write it.
import logging
import optparse
LOGGING_LEVELS = {'critical': logging.CRITICAL,
'error': logging.ERROR,
'warning': logging.WARNING,
'info': logging.INFO,
'debug': logging.DEBUG}
def main():
parser = optparse.OptionParser()
parser.add_option('-l', '--logging-level', help='Logging level')
parser.add_option('-f', '--logging-file', help='Logging file name')
(options, args) = parser.parse_args()
logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
logging.basicConfig(level=logging_level, filename=options.logging_file,
format='%(asctime)s %(levelname)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# Your program goes here.
# You can access command-line arguments using the args variable.
if __name__ == '__main__':
main()
And here is his explanation of how to use the above. Again, I don't get the credit for this:
By default, the logging module prints critical, error and warning messages. To change this so that all levels are printed, use:
$ ./your-program.py --logging=debug
To send log messages to a file called debug.log, use:
$ ./your-program.py --logging-level=debug --logging-file=debug.log
It is possible to print what Python lines are executed (thanks Geo!). This has any number of applications, for example, you could modify it to check when particular functions are called or add something like ## make it only track particular lines.
code.interact takes you into a interactive console
import code; code.interact(local=locals())
If you want to be able to easily access your console history look at: "Can I have a history mechanism like in the shell?" (will have to look down for it).
Auto-complete can be enabled for the interpreter.
ipdb is like pdb, with the awesomeness of ipython.
print statements
Some people recommend a debug_print function instead of print for easy disabling
The pprint module is invaluable for complex structures
the obvious way to debug a script
python -m pdb script.py
useful when that script raises an exception
useful when using virtualenv and pdb command is not running with the venvs python version.
if you don't know exactly where that script is
python -m pdb ``which <python-script-name>``
PyDev
PyDev has a pretty good interactive debugger. It has watch expressions, hover-to-evaluate, thread and stack listings and (almost) all the usual amenities you expect from a modern visual debugger. You can even attach to a running process and do remote debugging.
Like other visual debuggers, though, I find it useful mostly for simple problems, or for very complicated problems after I've tried everything else. I still do most of the heavy lifting with logging.
If you are familiar with Visual Studio, Python Tools for Visual Studio is what you look for.
Winpdb is very nice, and contrary to its name it's completely cross-platform.
It's got a very nice prompt-based and GUI debugger, and supports remote debugging.
In Vim, I have these three bindings:
map <F9> Oimport rpdb2; rpdb2.start_embedded_debugger("asdf") #BREAK<esc>
map <F8> Ofrom nose.tools import set_trace; set_trace() #BREAK<esc>
map <F7> Oimport traceback, sys; traceback.print_exception(*sys.exc_info()) #TRACEBACK<esc>
rpdb2 is a Remote Python Debugger, which can be used with WinPDB, a solid graphical debugger. Because I know you'll ask, it can do everything I expect a graphical debugger to do :)
I use pdb from nose.tools so that I can debug unit tests as well as normal code.
Finally, the F7 mapping will print a traceback (similar to the kind you get when an exception bubbles to the top of the stack). I've found it really useful more than a few times.
Defining useful repr() methods for your classes (so you can see what an object is) and using repr() or "%r" % (...) or "...{0!r}..".format(...) in your debug messages/logs is IMHO a key to efficient debugging.
Also, the debuggers mentioned in other answers will make use of the repr() methods.
Getting a stack trace from a running Python application
There are several tricks here. These include
Breaking into an interpreter/printing a stack trace by sending a signal
Getting a stack trace out of an unprepared Python process
Running the interpreter with flags to make it useful for debugging
If you don't like spending time in debuggers (and don't appreciate poor usability of pdb command line interface), you can dump execution trace and analyze it later. For example:
python -m trace -t setup.py install > execution.log
This will dump all source line of setup.py install execution to execution.log.
To make it easier to customize trace output and write your own tracers, I put together some pieces of code into xtrace module (public domain).
When possible, I debug using M-x pdb in emacs for source level debugging.
There is a full online course called "Software Debugging" by Andreas Zeller on Udacity, packed with tips about debugging:
Course Summary
In this class you will learn how to debug programs systematically, how
to automate the debugging process and build several automated
debugging tools in Python.
Why Take This Course?
At the end of this course you will have a solid understanding about
systematic debugging, will know how to automate debugging and will
have built several functional debugging tools in Python.
Prerequisites and Requirements
Basic knowledge of programming and Python at the level of Udacity
CS101 or better is required. Basic understanding of Object-oriented
programming is helpful.
Highly recommended.
if you want a nice graphical way to print your call stack in a readable fashion, check out this utility: https://github.com/joerick/pyinstrument
Run from command line:
python -m pyinstrument myscript.py [args...]
Run as a module:
from pyinstrument import Profiler
profiler = Profiler()
profiler.start()
# code you want to profile
profiler.stop()
print(profiler.output_text(unicode=True, color=True))
Run with django:
Just add pyinstrument.middleware.ProfilerMiddleware to MIDDLEWARE_CLASSES, then add ?profile to the end of the request URL to activate the profiler.
Closed. This question needs to be more focused. It is not currently accepting answers.
Closed 8 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What are your best tips for debugging Python?
Please don't just list a particular debugger without saying what it can actually do.
Related
What are good ways to make my Python code run first time? - This discusses minimizing errors
PDB
You can use the pdb module, insert pdb.set_trace() anywhere and it will function as a breakpoint.
>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)
To continue execution use c (or cont or continue).
It is possible to execute arbitrary Python expressions using pdb. For example, if you find a mistake, you can correct the code, then type a type expression to have the same effect in the running code
ipdb is a version of pdb for IPython. It allows the use of pdb with all the IPython features including tab completion.
It is also possible to set pdb to automatically run on an uncaught exception.
Pydb was written to be an enhanced version of Pdb. Benefits?
http://pypi.python.org/pypi/pudb, a full-screen, console-based Python debugger.
Its goal is to provide all the niceties of modern GUI-based debuggers in a more lightweight and keyboard-friendly package. PuDB allows you to debug code right where you write and test it – in a terminal. If you've worked with the excellent (but nowadays ancient) DOS-based Turbo Pascal or C tools, PuDB's UI might look familiar.
Nice for debugging standalone scripts, just run
python -m pudb.run my-script.py
If you are using pdb, you can define aliases for shortcuts. I use these:
# Ned's .pdbrc
# Print a dictionary, sorted. %1 is the dict, %2 is the prefix for the names.
alias p_ for k in sorted(%1.keys()): print "%s%-15s= %-80.80s" % ("%2",k,repr(%1[k]))
# Print the instance variables of a thing.
alias pi p_ %1.__dict__ %1.
# Print the instance variables of self.
alias ps pi self
# Print the locals.
alias pl p_ locals() local:
# Next and list, and step and list.
alias nl n;;l
alias sl s;;l
# Short cuts for walking up and down the stack
alias uu u;;u
alias uuu u;;u;;u
alias uuuu u;;u;;u;;u
alias uuuuu u;;u;;u;;u;;u
alias dd d;;d
alias ddd d;;d;;d
alias dddd d;;d;;d;;d
alias ddddd d;;d;;d;;d;;d
Logging
Python already has an excellent built-in logging module. You may want to use the logging template here.
The logging module lets you specify a level of importance; during debugging you can log everything, while during normal operation you might only log critical things. You can switch things off and on.
Most people just use basic print statements to debug, and then remove the print statements. It's better to leave them in, but disable them; then, when you have another bug, you can just re-enable everything and look your logs over.
This can be the best possible way to debug programs that need to do things quickly, such as networking programs that need to respond before the other end of the network connection times out and goes away. You might not have much time to single-step a debugger; but you can just let your code run, and log everything, then pore over the logs and figure out what's really happening.
EDIT: The original URL for the templates was: http://aymanh.com/python-debugging-techniques
This page is missing so I replaced it with a reference to the snapshot saved at archive.org: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-techniques
In case it disappears again, here are the templates I mentioned. This is code taken from the blog; I didn't write it.
import logging
import optparse
LOGGING_LEVELS = {'critical': logging.CRITICAL,
'error': logging.ERROR,
'warning': logging.WARNING,
'info': logging.INFO,
'debug': logging.DEBUG}
def main():
parser = optparse.OptionParser()
parser.add_option('-l', '--logging-level', help='Logging level')
parser.add_option('-f', '--logging-file', help='Logging file name')
(options, args) = parser.parse_args()
logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
logging.basicConfig(level=logging_level, filename=options.logging_file,
format='%(asctime)s %(levelname)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# Your program goes here.
# You can access command-line arguments using the args variable.
if __name__ == '__main__':
main()
And here is his explanation of how to use the above. Again, I don't get the credit for this:
By default, the logging module prints critical, error and warning messages. To change this so that all levels are printed, use:
$ ./your-program.py --logging=debug
To send log messages to a file called debug.log, use:
$ ./your-program.py --logging-level=debug --logging-file=debug.log
It is possible to print what Python lines are executed (thanks Geo!). This has any number of applications, for example, you could modify it to check when particular functions are called or add something like ## make it only track particular lines.
code.interact takes you into a interactive console
import code; code.interact(local=locals())
If you want to be able to easily access your console history look at: "Can I have a history mechanism like in the shell?" (will have to look down for it).
Auto-complete can be enabled for the interpreter.
ipdb is like pdb, with the awesomeness of ipython.
print statements
Some people recommend a debug_print function instead of print for easy disabling
The pprint module is invaluable for complex structures
the obvious way to debug a script
python -m pdb script.py
useful when that script raises an exception
useful when using virtualenv and pdb command is not running with the venvs python version.
if you don't know exactly where that script is
python -m pdb ``which <python-script-name>``
PyDev
PyDev has a pretty good interactive debugger. It has watch expressions, hover-to-evaluate, thread and stack listings and (almost) all the usual amenities you expect from a modern visual debugger. You can even attach to a running process and do remote debugging.
Like other visual debuggers, though, I find it useful mostly for simple problems, or for very complicated problems after I've tried everything else. I still do most of the heavy lifting with logging.
If you are familiar with Visual Studio, Python Tools for Visual Studio is what you look for.
Winpdb is very nice, and contrary to its name it's completely cross-platform.
It's got a very nice prompt-based and GUI debugger, and supports remote debugging.
In Vim, I have these three bindings:
map <F9> Oimport rpdb2; rpdb2.start_embedded_debugger("asdf") #BREAK<esc>
map <F8> Ofrom nose.tools import set_trace; set_trace() #BREAK<esc>
map <F7> Oimport traceback, sys; traceback.print_exception(*sys.exc_info()) #TRACEBACK<esc>
rpdb2 is a Remote Python Debugger, which can be used with WinPDB, a solid graphical debugger. Because I know you'll ask, it can do everything I expect a graphical debugger to do :)
I use pdb from nose.tools so that I can debug unit tests as well as normal code.
Finally, the F7 mapping will print a traceback (similar to the kind you get when an exception bubbles to the top of the stack). I've found it really useful more than a few times.
Defining useful repr() methods for your classes (so you can see what an object is) and using repr() or "%r" % (...) or "...{0!r}..".format(...) in your debug messages/logs is IMHO a key to efficient debugging.
Also, the debuggers mentioned in other answers will make use of the repr() methods.
Getting a stack trace from a running Python application
There are several tricks here. These include
Breaking into an interpreter/printing a stack trace by sending a signal
Getting a stack trace out of an unprepared Python process
Running the interpreter with flags to make it useful for debugging
If you don't like spending time in debuggers (and don't appreciate poor usability of pdb command line interface), you can dump execution trace and analyze it later. For example:
python -m trace -t setup.py install > execution.log
This will dump all source line of setup.py install execution to execution.log.
To make it easier to customize trace output and write your own tracers, I put together some pieces of code into xtrace module (public domain).
When possible, I debug using M-x pdb in emacs for source level debugging.
There is a full online course called "Software Debugging" by Andreas Zeller on Udacity, packed with tips about debugging:
Course Summary
In this class you will learn how to debug programs systematically, how
to automate the debugging process and build several automated
debugging tools in Python.
Why Take This Course?
At the end of this course you will have a solid understanding about
systematic debugging, will know how to automate debugging and will
have built several functional debugging tools in Python.
Prerequisites and Requirements
Basic knowledge of programming and Python at the level of Udacity
CS101 or better is required. Basic understanding of Object-oriented
programming is helpful.
Highly recommended.
if you want a nice graphical way to print your call stack in a readable fashion, check out this utility: https://github.com/joerick/pyinstrument
Run from command line:
python -m pyinstrument myscript.py [args...]
Run as a module:
from pyinstrument import Profiler
profiler = Profiler()
profiler.start()
# code you want to profile
profiler.stop()
print(profiler.output_text(unicode=True, color=True))
Run with django:
Just add pyinstrument.middleware.ProfilerMiddleware to MIDDLEWARE_CLASSES, then add ?profile to the end of the request URL to activate the profiler.
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 4 years ago.
Improve this question
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?
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.
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.
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.
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).
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.
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
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...
pip install django-pdb
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.
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:
Download and install it from https://microsoft.github.io/PTVS/
Set breakpoints and press F5.
Your breakpoint is hit, you can view/change the variables as easy as debugging C#/C++ programs.
That's all :)
If you want to debug Django using PTVS, you need to do the following:
In Project settings - General tab, set "Startup File" to "manage.py", the entry point of the Django program.
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.
Enjoy it.
I use pyDev with Eclipse really good, set break points, step into code, view values on any objects and variables, try it.
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.
From my perspective, we could break down common code debugging tasks into three distinct usage patterns:
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.
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.
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.
Add import pdb; pdb.set_trace() or breakpoint() (form python3.7) at the corresponding line in the Python code and execute it. The execution will stop with an interactive shell. In the shell you can execute Python code (i.e. print variables) or use commands such as:
c continue execution
n step to the next line within the same function
s step to the next line in this function or a called function
q quit the debugger/execution
Also see: https://poweruser.blog/setting-a-breakpoint-in-python-438e23fe6b28
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.
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.
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.
One of your best option to debug Django code is via wdb:
https://github.com/Kozea/wdb
wdb works with python 2 (2.6, 2.7), python 3 (3.2, 3.3, 3.4, 3.5) and pypy. Even better, it is possible to debug a python 2 program with a wdb server running on python 3 and vice-versa or debug a program running on a computer with a debugging server running on another computer inside a web page on a third computer!
Even betterer, it is now possible to pause a currently running python process/thread using code injection from the web interface. (This requires gdb and ptrace enabled)
In other words it's a very enhanced version of pdb directly in your browser with nice features.
Install and run the server, and in your code add:
import wdb
wdb.set_trace()
According to the author, main differences with respect to pdb are:
For those who don’t know the project, wdb is a python debugger like pdb, but with a slick web front-end and a lot of additional features, such as:
Source syntax highlighting
Visual breakpoints
Interactive code completion using jedi
Persistent breakpoints
Deep objects inspection using mouse Multithreading / Multiprocessing support
Remote debugging
Watch expressions
In debugger code edition
Popular web servers integration to break on error
In exception breaking during trace (not post-mortem) in contrary to the werkzeug debugger for instance
Breaking in currently running programs through code injection (on supported systems)
It has a great browser-based user interface. A joy to use! :)
I use PyCharm and different debug tools. Also have a nice articles set about easy set up those things for novices. You may start here. It tells about PDB and GUI debugging in general with Django projects. Hope someone would benefit from them.
If using Aptana for django development, watch this: http://www.youtube.com/watch?v=qQh-UQFltJQ
If not, consider using it.
Most options are alredy mentioned.
To print template context, I've created a simple library for that.
See https://github.com/edoburu/django-debugtools
You can use it to print template context without any {% load %} construct:
{% print var %} prints variable
{% print %} prints all
It uses a customized pprint format to display the variables in a <pre> tag.
I find Visual Studio Code is awesome for debugging Django apps. The standard python launch.json parameters run python manage.py with the debugger attached, so you can set breakpoints and step through your code as you like.
For those that can accidentally add pdb into live commits, I can suggest this extension of #Koobz answer:
#register.filter
def pdb(element):
from django.conf import settings
if settings.DEBUG:
import pdb
pdb.set_trace()
return element
From my own experience , there are two way:
use ipdb,which is a enhanced debugger likes pdb.
import ipdb;ipdb.set_trace() or breakpoint() (from python3.7)
use django shell ,just use the command below. This is very helpfull when you are developing a new view.
python manage.py shell
i highly suggest to use PDB.
import pdb
pdb.set_trace()
You can inspect all the variables values, step in to the function and much more.
https://docs.python.org/2/library/pdb.html
for checking out the all kind of request,response and hits to database.i am using django-debug-toolbar
https://github.com/django-debug-toolbar/django-debug-toolbar
As mentioned in other posts here - setting breakpoints in your code and walking thru the code to see if it behaves as you expected is a great way to learn something like Django until you have a good sense of how it all behaves - and what your code is doing.
To do this I would recommend using WingIde. Just like other mentioned IDEs nice and easy to use, nice layout and also easy to set breakpoints evaluate / modify the stack etc. Perfect for visualizing what your code is doing as you step through it. I'm a big fan of it.
Also I use PyCharm - it has excellent static code analysis and can help sometimes spot problems before you realize they are there.
As mentioned already django-debug-toolbar is essential - https://github.com/django-debug-toolbar/django-debug-toolbar
And while not explicitly a debug or analysis tool - one of my favorites is SQL Printing Middleware available from Django Snippets at https://djangosnippets.org/snippets/290/
This will display the SQL queries that your view has generated. This will give you a good sense of what the ORM is doing and if your queries are efficient or you need to rework your code (or add caching).
I find it invaluable for keeping an eye on query performance while developing and debugging my application.
Just one other tip - I modified it slightly for my own use to only show the summary and not the SQL statement.... So I always use it while developing and testing. I also added that if the len(connection.queries) is greater than a pre-defined threshold it displays an extra warning.
Then if I spot something bad (from a performance or number of queries perspective) is happening I turn back on the full display of the SQL statements to see exactly what is going on. Very handy when you are working on a large Django project with multiple developers.
use pdb or ipdb. Diffrence between these two is ipdb supports auto complete.
for pdb
import pdb
pdb.set_trace()
for ipdb
import ipdb
ipdb.set_trace()
For executing new line hit n key, for continue hit c key.
check more options by using help(pdb)
An additional suggestion.
You can leverage nosetests and pdb together, rather injecting pdb.set_trace() in your views manually. The advantage is that you can observe error conditions when they first start, potentially in 3rd party code.
Here's an error for me today.
TypeError at /db/hcm91dmo/catalog/records/
render_option() argument after * must be a sequence, not int
....
Error during template rendering
In template /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/crispy_forms/templates/bootstrap3/field.html, error at line 28
render_option() argument after * must be a sequence, not int
18
19 {% if field|is_checkboxselectmultiple %}
20 {% include 'bootstrap3/layout/checkboxselectmultiple.html' %}
21 {% endif %}
22
23 {% if field|is_radioselect %}
24 {% include 'bootstrap3/layout/radioselect.html' %}
25 {% endif %}
26
27 {% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
28
{% if field|is_checkbox and form_show_labels %}
Now, I know this means that I goofed the constructor for the form, and I even have good idea of which field is a problem. But, can I use pdb to see what crispy forms is complaining about, within a template?
Yes, I can. Using the --pdb option on nosetests:
tests$ nosetests test_urls_catalog.py --pdb
As soon as I hit any exception (including ones handled gracefully), pdb stops where it happens and I can look around.
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/forms.py", line 537, in __str__
return self.as_widget()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/forms.py", line 593, in as_widget
return force_text(widget.render(name, self.value(), attrs=attrs))
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py", line 513, in render
options = self.render_options(choices, [value])
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py", line 543, in render_options
output.append(self.render_option(selected_choices, *option))
TypeError: render_option() argument after * must be a sequence, not int
INFO lib.capture_middleware log write_to_index(http://localhost:8082/db/hcm91dmo/catalog/records.html)
INFO lib.capture_middleware log write_to_index:end
> /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/forms/widgets.py(543)render_options()
-> output.append(self.render_option(selected_choices, *option))
(Pdb) import pprint
(Pdb) pprint.PrettyPrinter(indent=4).pprint(self)
<django.forms.widgets.Select object at 0x115fe7d10>
(Pdb) pprint.PrettyPrinter(indent=4).pprint(vars(self))
{ 'attrs': { 'class': 'select form-control'},
'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]],
'is_required': False}
(Pdb)
Now, it's clear that my choices argument to the crispy field constructor was as it was a list within a list, rather than a list/tuple of tuples.
'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]]
The neat thing is that this pdb is taking place within crispy's code, not mine and I didn't need to insert it manually.
During development, adding a quick
assert False, value
can help diagnose problems in views or anywhere else, without the need to use a debugger.
I really like Python because I can use its shell to explore things.
Is it possible to do the same while developing a django app?
I mean, is it possible to do:
def process_request(request):
...
if(request.FILES != none):
__builtins__.debug_request = request
showPythonShell();
...
so I can experiment with the request?
Thanks :D
Install ipython and substitute showPythonShell() with:
from IPython import embed; embed();
This will do exactly what you are expecting i.e. launch an ipython shell from within your if statement. The benefits of having an ipython shell are tab completion, magic functions etc. as reviewed here. I've been developing in python for quite some time now and this is primarily the method I use to debug anything, including django.
This can be done using the python debugger: pdb
Or even better ipdb, which gives you tab completion, syntax highlighting and other IPython features.
if(request.FILES != none):
import ipdb; ipdb.set_trace()
As soon as the line is reached you are dropped to a debugging shell where you can examine the request. Check the pdb docs for all available commands.
Here is a really good blog post explaining all the details: http://aymanh.com/python-debugging-techniques
Closed. This question needs to be more focused. It is not currently accepting answers.
Closed 8 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What are your best tips for debugging Python?
Please don't just list a particular debugger without saying what it can actually do.
Related
What are good ways to make my Python code run first time? - This discusses minimizing errors
PDB
You can use the pdb module, insert pdb.set_trace() anywhere and it will function as a breakpoint.
>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)
To continue execution use c (or cont or continue).
It is possible to execute arbitrary Python expressions using pdb. For example, if you find a mistake, you can correct the code, then type a type expression to have the same effect in the running code
ipdb is a version of pdb for IPython. It allows the use of pdb with all the IPython features including tab completion.
It is also possible to set pdb to automatically run on an uncaught exception.
Pydb was written to be an enhanced version of Pdb. Benefits?
http://pypi.python.org/pypi/pudb, a full-screen, console-based Python debugger.
Its goal is to provide all the niceties of modern GUI-based debuggers in a more lightweight and keyboard-friendly package. PuDB allows you to debug code right where you write and test it – in a terminal. If you've worked with the excellent (but nowadays ancient) DOS-based Turbo Pascal or C tools, PuDB's UI might look familiar.
Nice for debugging standalone scripts, just run
python -m pudb.run my-script.py
If you are using pdb, you can define aliases for shortcuts. I use these:
# Ned's .pdbrc
# Print a dictionary, sorted. %1 is the dict, %2 is the prefix for the names.
alias p_ for k in sorted(%1.keys()): print "%s%-15s= %-80.80s" % ("%2",k,repr(%1[k]))
# Print the instance variables of a thing.
alias pi p_ %1.__dict__ %1.
# Print the instance variables of self.
alias ps pi self
# Print the locals.
alias pl p_ locals() local:
# Next and list, and step and list.
alias nl n;;l
alias sl s;;l
# Short cuts for walking up and down the stack
alias uu u;;u
alias uuu u;;u;;u
alias uuuu u;;u;;u;;u
alias uuuuu u;;u;;u;;u;;u
alias dd d;;d
alias ddd d;;d;;d
alias dddd d;;d;;d;;d
alias ddddd d;;d;;d;;d;;d
Logging
Python already has an excellent built-in logging module. You may want to use the logging template here.
The logging module lets you specify a level of importance; during debugging you can log everything, while during normal operation you might only log critical things. You can switch things off and on.
Most people just use basic print statements to debug, and then remove the print statements. It's better to leave them in, but disable them; then, when you have another bug, you can just re-enable everything and look your logs over.
This can be the best possible way to debug programs that need to do things quickly, such as networking programs that need to respond before the other end of the network connection times out and goes away. You might not have much time to single-step a debugger; but you can just let your code run, and log everything, then pore over the logs and figure out what's really happening.
EDIT: The original URL for the templates was: http://aymanh.com/python-debugging-techniques
This page is missing so I replaced it with a reference to the snapshot saved at archive.org: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-techniques
In case it disappears again, here are the templates I mentioned. This is code taken from the blog; I didn't write it.
import logging
import optparse
LOGGING_LEVELS = {'critical': logging.CRITICAL,
'error': logging.ERROR,
'warning': logging.WARNING,
'info': logging.INFO,
'debug': logging.DEBUG}
def main():
parser = optparse.OptionParser()
parser.add_option('-l', '--logging-level', help='Logging level')
parser.add_option('-f', '--logging-file', help='Logging file name')
(options, args) = parser.parse_args()
logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
logging.basicConfig(level=logging_level, filename=options.logging_file,
format='%(asctime)s %(levelname)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# Your program goes here.
# You can access command-line arguments using the args variable.
if __name__ == '__main__':
main()
And here is his explanation of how to use the above. Again, I don't get the credit for this:
By default, the logging module prints critical, error and warning messages. To change this so that all levels are printed, use:
$ ./your-program.py --logging=debug
To send log messages to a file called debug.log, use:
$ ./your-program.py --logging-level=debug --logging-file=debug.log
It is possible to print what Python lines are executed (thanks Geo!). This has any number of applications, for example, you could modify it to check when particular functions are called or add something like ## make it only track particular lines.
code.interact takes you into a interactive console
import code; code.interact(local=locals())
If you want to be able to easily access your console history look at: "Can I have a history mechanism like in the shell?" (will have to look down for it).
Auto-complete can be enabled for the interpreter.
ipdb is like pdb, with the awesomeness of ipython.
print statements
Some people recommend a debug_print function instead of print for easy disabling
The pprint module is invaluable for complex structures
the obvious way to debug a script
python -m pdb script.py
useful when that script raises an exception
useful when using virtualenv and pdb command is not running with the venvs python version.
if you don't know exactly where that script is
python -m pdb ``which <python-script-name>``
PyDev
PyDev has a pretty good interactive debugger. It has watch expressions, hover-to-evaluate, thread and stack listings and (almost) all the usual amenities you expect from a modern visual debugger. You can even attach to a running process and do remote debugging.
Like other visual debuggers, though, I find it useful mostly for simple problems, or for very complicated problems after I've tried everything else. I still do most of the heavy lifting with logging.
If you are familiar with Visual Studio, Python Tools for Visual Studio is what you look for.
Winpdb is very nice, and contrary to its name it's completely cross-platform.
It's got a very nice prompt-based and GUI debugger, and supports remote debugging.
In Vim, I have these three bindings:
map <F9> Oimport rpdb2; rpdb2.start_embedded_debugger("asdf") #BREAK<esc>
map <F8> Ofrom nose.tools import set_trace; set_trace() #BREAK<esc>
map <F7> Oimport traceback, sys; traceback.print_exception(*sys.exc_info()) #TRACEBACK<esc>
rpdb2 is a Remote Python Debugger, which can be used with WinPDB, a solid graphical debugger. Because I know you'll ask, it can do everything I expect a graphical debugger to do :)
I use pdb from nose.tools so that I can debug unit tests as well as normal code.
Finally, the F7 mapping will print a traceback (similar to the kind you get when an exception bubbles to the top of the stack). I've found it really useful more than a few times.
Defining useful repr() methods for your classes (so you can see what an object is) and using repr() or "%r" % (...) or "...{0!r}..".format(...) in your debug messages/logs is IMHO a key to efficient debugging.
Also, the debuggers mentioned in other answers will make use of the repr() methods.
Getting a stack trace from a running Python application
There are several tricks here. These include
Breaking into an interpreter/printing a stack trace by sending a signal
Getting a stack trace out of an unprepared Python process
Running the interpreter with flags to make it useful for debugging
If you don't like spending time in debuggers (and don't appreciate poor usability of pdb command line interface), you can dump execution trace and analyze it later. For example:
python -m trace -t setup.py install > execution.log
This will dump all source line of setup.py install execution to execution.log.
To make it easier to customize trace output and write your own tracers, I put together some pieces of code into xtrace module (public domain).
When possible, I debug using M-x pdb in emacs for source level debugging.
There is a full online course called "Software Debugging" by Andreas Zeller on Udacity, packed with tips about debugging:
Course Summary
In this class you will learn how to debug programs systematically, how
to automate the debugging process and build several automated
debugging tools in Python.
Why Take This Course?
At the end of this course you will have a solid understanding about
systematic debugging, will know how to automate debugging and will
have built several functional debugging tools in Python.
Prerequisites and Requirements
Basic knowledge of programming and Python at the level of Udacity
CS101 or better is required. Basic understanding of Object-oriented
programming is helpful.
Highly recommended.
if you want a nice graphical way to print your call stack in a readable fashion, check out this utility: https://github.com/joerick/pyinstrument
Run from command line:
python -m pyinstrument myscript.py [args...]
Run as a module:
from pyinstrument import Profiler
profiler = Profiler()
profiler.start()
# code you want to profile
profiler.stop()
print(profiler.output_text(unicode=True, color=True))
Run with django:
Just add pyinstrument.middleware.ProfilerMiddleware to MIDDLEWARE_CLASSES, then add ?profile to the end of the request URL to activate the profiler.