How to debug in Django, the good way?
所以,我开始学习用python和后来的django编写代码。第一次,我很难看到回溯,并真正弄清楚我做错了什么,语法错误在哪里。一段时间过去了,一段时间过去了,我想我有一个调试Django代码的例行程序。由于这是在我早期的编码经验中完成的,我坐下来想知道我是如何做到这一点是无效的,并且可以更快地完成。我通常设法找到并纠正代码中的错误,但我想知道我是否应该更快地完成它?
我通常只使用Django在启用时提供的调试信息。当事情像我想象的那样结束时,我会用语法错误打断代码流,并查看流中那个点的变量,找出代码在哪里做了我想要做的以外的事情。
但这能得到改善吗?是否有一些好的工具或更好的方法来调试Django代码?
有很多方法可以做到,但最简单的方法是使用Python调试器。只需在django视图函数中添加以下行:
1 | import pdb; pdb.set_trace() |
如果尝试在浏览器中加载该页,浏览器将挂起,并提示您对实际执行的代码进行调试。
但是,还有其他选择(我不建议这样做):
1 2 3 4 5 | * return HttpResponse({variable to inspect}) * print {variable to inspect} * raise Exception({variable to inspect}) |
但是对于所有类型的Python代码,强烈推荐使用Python调试器(PDB)。如果您已经进入PDB,那么您还需要了解使用IPython进行调试的IPDB。
PDB的一些更有用的扩展是
PDB++,由Antash提出。
Pudb,Patdujour建议。
在Django中使用Python调试器,由Seafangs建议。
我真的很喜欢Werkzeug的交互式调试器。它类似于Django的调试页面,只是在每一个回溯级别上都有一个交互式shell。如果使用django扩展,您将得到一个
当然,您应该只在本地运行它,因为它赋予任何拥有浏览器的人在服务器上下文中执行任意python代码的权利。
模板标签有点快:
1 2 3 4 | @register.filter def pdb(element): import pdb; pdb.set_trace() return element |
现在,在一个模板中,您可以执行
这是一种非常好的方法,可以在对象到达模板时看到它发生了什么。
有一些工具可以很好地协作,并且可以使调试任务变得更容易。
最重要的是django调试工具栏。
然后,您需要使用python日志记录工具进行良好的日志记录。您可以将日志输出发送到日志文件,但更简单的选项是将日志输出发送到Fireython。要使用它,您需要将firefox浏览器与firebug扩展一起使用。Fireython包含一个Firebug插件,它将在Firebug选项卡中显示任何服务器端登录。
Firebug本身对于调试您开发的任何应用程序的javascript方面也是至关重要的。(假设您当然有一些JS代码)。
我还喜欢使用django viewtools以交互方式使用pdb调试视图,但我并没有使用太多。
有更多有用的工具,如推土机,用于跟踪内存泄漏(这里的答案中也有其他好的建议,以便进行内存跟踪)。
我使用pycharm(与eclipse相同的pydev引擎)。真的有助于我在视觉上能够逐步通过我的代码并看到正在发生的事情。
到目前为止,几乎所有的事情都已经提到了,所以我只想补充一点,我们可以使用ipdb.set_trace(),它使用ipython,因此更强大(自动完成和其他优点)。这需要ipdb包,所以您只需要EDOCX1[4]
我把
安装只是…
现在可以运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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) |
运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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) |
这个项目是在Github上主办的,当然欢迎捐款。
调试python的最简单方法是使用ptv(用于Visual Studio的python工具),特别是对于用于Visual Studio的程序员。步骤很简单:
如果要使用PTV调试Django,需要执行以下操作:
我将pydev与eclipse结合使用非常好,设置断点,单步执行代码,查看任何对象和变量的值,并尝试一下。
我使用Pycharm并一直支持它。这花了我一点钱,但我不得不说,我从中得到的好处是无价的。我试过从控制台进行调试,我确实给了人们很多可以做到这一点的信任,但是对于我来说,能够可视化地调试我的应用程序是非常好的。
不过,我得说,《魔女》的确需要很多记忆。但同样的,生活中没有什么好东西是自由的。他们刚推出最新版本3。它还可以与Django、Flask和Google Appengine配合使用。所以,总而言之,对于任何开发人员来说,它都是一个很好的方便工具。
如果您还没有使用它,我建议您使用试用版30天,看看Pycharm的强大功能。我确信还有其他工具可用,比如Aptana。但我想我也很喜欢小魔女的样子。我觉得在那里调试我的应用程序很舒服。
从我的角度来看,我们可以将常见的代码调试任务分解为三种不同的使用模式:
啊,是的,模板的不幸。(对我和同事来说)最常见的问题是上下文错误:要么你没有变量,要么你的变量没有属性。如果您使用的是调试工具栏,只需检查"模板"部分的上下文,或者,如果还不够,则在上下文填满后在视图代码中设置一个中断。
就这样。
有时,当我想用一种特定的方法四处探索,并且召唤PDB太麻烦时,我会补充:
1 | import IPython; IPython.embed() |
我强烈推荐EPDB(扩展的python调试器)。
网址:https://bitback.org/dugan/epdb
我喜欢EPDB调试Django或其他PythonWebServer的一件事是epdb.serve()命令。这将设置一个跟踪,并在您可以连接的本地端口上提供该跟踪。典型用例:
我有一个观点,我想一步一步地进行。我将在要设置跟踪的点插入以下内容。
1 | import epdb; epdb.serve() |
一旦执行了这段代码,我就打开一个python解释器并连接到服务实例。我可以使用标准PDB命令(如N、S等)分析所有值并逐步完成代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 |
你可以随时学习输入EPDB帮助。
如果要同时服务或连接到多个EPDB实例,可以指定要侦听的端口(默认值为8080)。即。
1 2 3 | import epdb; epdb.serve(4242) >> import epdb; epdb.connect(host='192.168.3.2', port=4242) |
如果未指定,则主机默认为"localhost"。我把它放在这里演示如何使用它来调试本地实例以外的东西,比如本地LAN上的开发服务器。显然,如果这样做,请注意设置跟踪永远不会进入生产服务器!
作为一个简短的说明,您仍然可以使用EPDB(
我刚找到WDB(http://www.rkblog.rk.edu.pl/w/p/debugging-python-code-browser-wdb-debugger/?Goback=%2egde_25827_成员_255996401)。它有一个非常好的用户界面/GUI,上面有所有的铃声和口哨。作者说这是关于WDB的-
"有像Pycharm这样的IDE拥有自己的调试器。它们提供类似或相同的功能集…但是要使用它们,您必须使用那些特定的IDE(其中一些是非免费的,或者可能不适用于所有平台)。根据需要选择合适的工具。"
以为我会把它传下去。
还有一篇关于Python调试器的非常有用的文章:https://zapier.com/engineering/debugging-python-boss/
最后,如果您想在Django中看到一个很好的调用堆栈的图形打印输出,请签出:https://github.com/joerick/pyinstrument.只需将pyinstrument.middleware.profilermiddleware添加到中间件类,然后添加?配置文件到激活探查器的请求URL的末尾。
也可以从命令行运行pyinstrument或将其作为模块导入。
我使用pycharm和不同的调试工具。还有一篇很好的文章,关于如何为新手轻松设置这些东西。你可以从这里开始。它介绍了在Django项目中的PDB和GUI调试。希望有人能从中受益。
调试Django代码的最佳选择之一是通过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.
安装并运行服务器,在代码中添加:
1 2 | import wdb wdb.set_trace() |
作者认为,与
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)
它有一个很棒的基于浏览器的用户界面。使用的乐趣!:)
大多数选项都已提到。为了打印模板上下文,我创建了一个简单的库。请参阅https://github.com/edoburu/django-debugtools
您可以使用它来打印模板上下文,而不需要任何
1 2 | {% print var %} prints variable {% print %} prints all |
它使用定制的pprint格式在
如果使用Aptana进行Django开发,请观看:http://www.youtube.com/watch?V= QQH UQFLTJQ
如果没有,考虑使用它。
我发现Visual Studio代码非常适合调试Django应用程序。标准的python launch.json参数在附加了调试器的情况下运行
对于那些可能意外地将PDB添加到实时提交中的人,我可以建议扩展koobz答案:
1 2 3 4 5 6 7 | @register.filter def pdb(element): from django.conf import settings if settings.DEBUG: import pdb pdb.set_trace() return element |
在python代码的相应行添加
- 继续执行
n 在同一功能内进入下一行s 单步执行此函数或被调用函数的下一行q 退出调试程序/执行
另请参见:https://poweruser.blog/setting-a-breakpoint-in-python-438e23fe6b28
我强烈建议使用PDB。
1 2 | import pdb pdb.set_trace() |
您可以检查所有变量的值,单步执行函数等等。https://docs.python.org/2/library/pdb.html网站
用于检查所有类型的请求、响应和对数据库的命中。我使用的是Django调试工具栏。https://github.com/django-debug-toolbar/django-debug-toolbar
正如这里其他文章所提到的,在代码中设置断点并浏览代码以查看其行为是否如您预期的那样,这是一个很好的学习方法,比如Django,直到您对所有代码的行为以及代码正在做什么有了很好的了解。
为此,我建议使用Wingide。和前面提到的IDES一样,它很好且易于使用,布局也很好,而且还易于设置断点、评估/修改堆栈等,非常适合在代码执行过程中可视化代码。我很喜欢它。
另外,我还使用了pycharm——它具有出色的静态代码分析功能,可以帮助您在意识到问题存在之前发现问题。
如前所述,django调试工具栏是必不可少的-https://github.com/django-debug-toolbar/django-debug-toolbar
虽然没有明确的调试或分析工具,但我最喜欢的是jjango代码段提供的SQL打印中间件,网址为https://django snippets.org/snippets/2900。/
这将显示视图生成的SQL查询。这将使您很好地了解ORM在做什么,以及您的查询是否有效,或者您需要重新编写代码(或者添加缓存)。
我发现它对于在开发和调试应用程序时关注查询性能非常有价值。
另外一个技巧-我对它进行了一些修改,以供自己使用,只显示摘要而不显示SQL语句…所以我总是在开发和测试时使用它。我还补充说,如果len(connection.queries)大于预先定义的阈值,它将显示额外的警告。
然后,如果我发现(从性能或查询数量的角度来看)发生了一些不好的事情,我将重新打开SQL语句的完整显示,以准确地看到正在发生的事情。与多个开发人员一起处理大型Django项目时非常方便。
根据我自己的经验,有两种方法:
使用IPDB,这是一个增强的调试器,比如PDB。
使用django shell,只需使用下面的命令。这在开发新视图时非常有用。
一个额外的建议。
您可以同时利用nosetest和pdb,而不是手动在视图中注入
今天我有个错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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 %} |
现在,我知道这意味着我在表单的构造器上加了个Google,我甚至对哪个字段有了很好的了解。但是,我可以使用pdb来查看模板中的crispy表单抱怨什么吗?
是的,我能。在nose测试中使用--pdb选项:
一旦我遇到任何异常(包括处理得当的异常),PDB就会在它发生的地方停止,我可以四处看看。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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) |
现在,很明显,crispy字段构造函数的choices参数是列表中的列表,而不是元组列表/元组。
1 | 'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]] |
最有趣的是,这个PDB发生在Crispy的代码中,而不是我的代码,我不需要手动插入它。
使用
对于PDB
1 2 | import pdb pdb.set_trace() |
对于IPDB
1 2 | import ipdb ipdb.set_trace() |
对于执行新行,点击
在开发过程中,添加一个
1 | assert False, value |
可以帮助诊断视图或其他任何地方的问题,而无需使用调试器。