如何在Django中调试,好方法?

所以,我开始在PythonDjango中学习编码。第一次很难查看回溯并真正找出我做错了什么以及语法错误在哪里。现在已经过去了一段时间,在调试Django代码的过程中,我想我已经有了一个例行程序。由于这是在我早期的编程经验中完成的,我坐下来思考我这样做是否无效,是否可以更快地完成。我通常设法找到并纠正代码中的错误,但我想知道我是否应该更快地完成它?

我通常只使用Django启用时提供的调试信息。当事情确实像我想象的那样结束时,我用一个语法错误破坏了代码流,并查看流中那个点的变量,以找出代码在哪里做了与我想要的不同的事情。

但这种情况还能改善吗?是否有一些更好的工具或方法来调试Django代码?

302952 次浏览
有很多方法可以做到这一点,但最直接的是简单 使用Python调试器。只需在Django视图函数中添加如下一行:

import pdb; pdb.set_trace()

breakpoint()  #from Python3.7

如果您试图在浏览器中加载该页,浏览器将挂起,并提示您对实际执行的代码进行调试。

但是也有其他的选择(我不推荐):

* 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建议。

有一些工具配合得很好,可以使您的调试任务更容易。

最重要的是Django调试工具栏

然后需要使用Python 日志记录工具进行良好的日志记录。您可以将日志输出发送到日志文件,但是更简单的选择是将日志输出发送到firepython。要使用此功能,您需要使用带有firebug扩展名的Firefox浏览器。Firepython包含一个firebug插件,可以在firebug选项卡中显示任何服务器端日志记录。

Firebug本身对于调试您所开发的任何应用程序的Javascript方面也很重要。(当然前提是你有一些JS代码)。

我也喜欢使用pdb交互调试视图的django-viewtools,但我并不经常使用它。

还有更有用的工具,如dozer,可以跟踪内存泄漏(在SO的回答中也有其他关于内存跟踪的好建议)。

我使用pyDev中与Eclipse真的很好,设置断点,进入代码,查看任何对象和变量的值,尝试它。

我非常喜欢Werkzeug的交互式调试器。它类似于Django的调试页面,除了在回溯的每一层都有一个交互式shell。如果您使用django-extensions,您将得到runserver_plus管理命令,该命令将启动开发服务器,并在异常时为您提供Werkzeug的调试器。

当然,您应该只在本地运行它,因为它赋予任何使用浏览器的人在服务器上下文中执行任意python代码的权利。

一个关于模板标签的小窍门:

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

现在,在模板中,您可以执行\{\{ template_var|pdb }}并输入pdb会话(假设您正在运行本地devel服务器),在那里您可以检查element到您的内心内容。

这是一种很好的方式,可以看到当对象到达模板时发生了什么。

到目前为止,几乎所有的东西都已经提到了,所以我只补充一点,可以使用pdb.set_trace()而不是ipdb.set_trace (),它使用iPython,因此更强大(自动完成和其他好东西)。这需要ipdb包,所以你只需要pip install ipdb

我使用PyCharm(与eclipse相同的pydev引擎)。真的帮助我能够直观地逐级检查我的代码,并看到发生了什么。

我已经把django-pdb推到PyPI。 这是一个简单的应用程序,这意味着你不需要编辑你的源代码,每次你想进入pdb

安装只是…

  1. # EYZ0
  2. 添加'django_pdb'INSTALLED_APPS

你现在可以运行:manage.py runserver --pdb在每个视图的开始进入pdb…

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)

然后运行:manage.py test --pdb在测试失败/错误时进入pdb…

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,当然欢迎贡献。

如果使用Aptana进行django开发,请注意:http://www.youtube.com/watch?v=qQh-UQFltJQ

如果没有,考虑使用它。

调试python最简单的方法——特别是对于习惯了Visual Studio的程序员来说——是使用PTVS (python Tools for Visual Studio)。 步骤很简单:

  1. https://microsoft.github.io/PTVS/下载并安装它
  2. 设置断点并按F5。
  3. 您的断点被击中,您可以查看/更改变量,就像调试c# / c++程序一样简单。
  4. 这就是全部:)

如果你想使用PTVS调试Django,你需要做以下事情:

  1. 在项目设置-常规选项卡中,设置“启动文件”;到“manage.py”,Django程序的入口点。
  2. 在项目设置-调试选项卡中,设置“脚本参数”;到“runserver—noreload”。关键是“——noreload"在这里。如果你不设置它,你的断点就不会被击中。
  3. 享受它。
大多数选项已经提到了。 为了打印模板上下文,我为此创建了一个简单的库。 看到# EYZ0 < / p >

你可以使用它来打印模板上下文,而不需要任何{% load %}结构:

{% print var %}   prints variable
{% print %}       prints all

它使用定制的pprint格式在<pre>标记中显示变量。

我强烈推荐epdb(扩展Python调试器)。

https://bitbucket.org/dugan/epdb

我喜欢用epdb来调试Django或其他Python web服务器的一个原因是epdb.serve()命令。这将设置跟踪,并在您可以连接到的本地端口上提供该跟踪。典型用例:

我有一个视图,我想一步一步地讲。我将在我想要设置跟踪的位置插入以下内容。

import epdb; epdb.serve()

一旦执行了这段代码,我打开一个Python解释器并连接到服务实例。我可以分析所有的值,并使用标准pdb命令(如n, s等)逐级遍历代码。

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实例提供服务或连接到多个epdb实例,可以指定监听的端口(默认为8080)。即。

import epdb; epdb.serve(4242)


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

如果没有指定,主机默认为'localhost'。我在这里介绍它是为了演示如何使用它来调试本地实例以外的东西,比如本地LAN上的开发服务器。显然,如果您这样做,请注意设置跟踪永远不会出现在您的生产服务器上!

简要说明一下,您仍然可以使用epdb (import epdb; epdb.set_trace())执行与接受的答案相同的操作,但我想强调一下服务功能,因为我发现它非常有用。

我使用PyCharm和不同的调试工具。还有一篇不错的文章介绍如何为新手设置这些东西。它讲述了Django项目中PDB和GUI的调试。希望有人能从中受益。

我刚找到wdb (http://www.rkblog.rk.edu.pl/w/p/debugging-python-code-browser-wdb-debugger/?goback=%2Egde_25827_member_255996401)。它有一个非常漂亮的用户界面/ GUI,所有的铃铛和口哨。作者这样说wdb -

“像PyCharm这样的ide有自己的调试器。它们提供了相似或相同的功能……然而,要使用它们,你必须使用那些特定的ide(其中一些是非免费的,或者可能不适用于所有平台)。根据你的需要选择合适的工具。”

我想我应该把它传下去。

这也是一篇关于python调试器的非常有用的文章: # EYZ0 < / p >

最后,如果你想在Django中看到一个漂亮的调用堆栈的图形打印输出,checkout: # EYZ0。只需将pyinstrument.middleware.ProfilerMiddleware添加到MIDDLEWARE_CLASSES中,然后将?profile添加到请求URL的末尾以激活剖析器。< / p >

也可以从命令行或导入作为模块运行pyinstrument。

有时,当我想在一个特定的方法中探索,而召唤pdb太麻烦时,我会补充:

import IPython; IPython.embed()

IPython.embed()将启动一个IPython shell,该shell可以从您调用它的地方访问局部变量。

我使用PyCharm并一直坚持使用它。我花了一点钱,但我不得不说我从中得到的好处是无价的。我尝试过从控制台调试,我确实很信任那些能做到这一点的人,但对我来说,能够直观地调试我的应用程序是很棒的。

不过我不得不说,PyCharm确实占用了很多内存。但话说回来,生活中没有什么好东西是免费的。他们刚刚发布了最新版本3。它也可以很好地与Django, Flask和谷歌AppEngine一起使用。所以,总而言之,我认为这是任何开发人员都可以拥有的一个非常方便的工具。

如果你还没有使用它,我建议你试用30天,看看PyCharm的强大功能。我相信还有其他可用的工具,比如Aptana。但我想我也喜欢PyCharm的外观。我觉得在那里调试我的应用程序很舒服。

我强烈建议使用PDB。

import pdb
pdb.set_trace()
你可以检查所有变量的值,进入函数和更多。 # EYZ0 < / p >

用于检查对数据库的各种请求、响应和命中。我正在使用django-debug-toolbar # EYZ0 < / p >

正如在其他文章中提到的,在你的代码中设置断点,然后遍历代码,看看它是否像你预期的那样运行,这是学习像Django这样的东西的好方法,直到你对它的所有行为以及你的代码在做什么有很好的感觉。

要做到这一点,我建议使用WingIde。就像其他提到的ide一样,很好很容易使用,布局很好,也很容易设置断点,计算/修改堆栈等。完美的可视化你的代码正在做什么,因为你逐步通过它。我是它的超级粉丝。

我还使用PyCharm——它有出色的静态代码分析,有时可以帮助你在意识到问题之前发现问题。

如前所述,django-debug-toolbar是必不可少的https://github.com/django-debug-toolbar/django-debug-toolbar

虽然不是一个明确的调试或分析工具,但我最喜欢的工具之一是SQL打印中间件,可以从Django snippet的https://djangosnippets.org/snippets/290/中获得

这将显示视图生成的SQL查询。这将使您很好地了解ORM正在做什么,以及您的查询是否有效,或者您是否需要重做代码(或添加缓存)。

我发现它对于在开发和调试应用程序时监视查询性能非常有用。

还有一个技巧——我为自己的使用对它进行了稍微修改,只显示摘要而不显示SQL语句....所以我总是在开发和测试时使用它。我还补充说,如果len(connection.queries)大于预定义的阈值,它会显示一个额外的警告。

然后,如果我发现发生了一些不好的事情(从性能或查询数量的角度来看),我会返回SQL语句的完整显示,以查看到底发生了什么。当你与多个开发人员一起开发一个大型Django项目时,这非常方便。

从我的角度来看,我们可以将常见的代码调试任务分解为三种不同的使用模式:

  1. 引发异常: runserver_plus' Werkzeug调试器来拯救。在所有跟踪级别上运行自定义代码的能力是一个杀手。如果你完全被困住了,你可以创建一个Gist来分享,只需点击一下。
  2. 页面被渲染,但结果错误:再次,Werkzeug岩石。要在代码中设置断点,只需在想要停止的位置键入assert False
  3. 代码运行错误,但快速看没有帮助。很可能是算法问题。叹息。然后我通常会启动控制台调试器PuDB: import pudb; pudb.set_trace()。与[i]pdb相比的主要优点是PuDB(看起来就像你在80年代一样)使得设置自定义手表表达式变得轻而易举。使用GUI调试一堆嵌套循环要简单得多。

啊,是的,模板的问题。最常见的问题(对我和我的同事来说)是错误的上下文:要么你没有变量,要么你的变量没有某些属性。如果你使用调试工具栏,只检查“Templates”部分的上下文,或者,如果这还不够,在你的上下文被填充后,在你的视图代码中设置一个断点。

就这样。

另外一个建议。

您可以一起利用nosetestspdb,而不是手动在视图中注入pdb.set_trace()。这样做的好处是,您可以在错误条件第一次启动时观察到它们,可能是在第三方代码中。

这是我今天的一个错误。

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 %}

现在,我知道这意味着我把表单的构造函数弄糊涂了,我甚至很清楚哪个字段有问题。但是,我可以用pdb看看脆皮的形式是抱怨,在模板内?

是的,我会。在nosetests中使用——pdb选项:

# EYZ0

一旦我碰到任何异常(包括优雅地处理的异常),pdb就会停止,我可以四处查看。

  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 field构造函数的choices参数是一个列表中的列表,而不是元组中的list/tuple。

 'choices': [[('_', 'any type'), (7, (7, 'type 7', 'RECTYPE_TABLE'))]]

整洁的事情是,这个pdb发生在脆皮的代码,而不是我的,我不需要手动插入它。

使用pdbipdb。这两者的区别是ipdb支持自动完成。

pdb的

import pdb
pdb.set_trace()

对于ipdb

import ipdb
ipdb.set_trace()

执行换行按n键,继续按c键。 使用help(pdb)

检查更多选项

在开发过程中,快速添加

assert False, value

可以帮助诊断视图或其他任何地方的问题,而不需要使用调试器。

我发现Visual Studio Code用于调试Django应用程序非常棒。标准的python启动。json参数运行python manage.py,并附带调试器,这样你就可以设置断点并按自己的喜好逐步执行代码。

对于那些不小心将pdb添加到实时提交的人,我可以建议这个扩展#Koobz的答案:

@register.filter
def pdb(element):
from django.conf import settings
if settings.DEBUG:
import pdb
pdb.set_trace()
return element
调试Django代码的最佳选择之一是通过wdb: # EYZ0 < / p >

wdb工作与python 2 (2.6, 2.7), python 3(3.2, 3.3, 3.4, 3.5)和pypy。更好的是,可以使用运行在python3上的wdb服务器来调试python2程序,反之亦然,或者使用运行在另一台计算机上的调试服务器在第三台计算机上的网页中调试运行在一台计算机上的程序! 更好的是,现在可以使用web界面的代码注入来暂停当前正在运行的python进程/线程。(这需要启用gdb和ptrace) 换句话说,它是一个非常增强的版本的pdb直接在你的浏览器中具有很好的功能

安装并运行服务器,并在代码中添加:

import wdb
wdb.set_trace()

根据作者的说法,关于pdb的主要区别是:

对于那些不了解项目的人,wdb是一个像pdb一样的python调试器,但是有一个光滑的web前端和许多额外的功能,例如:

  • 源语法突出显示
  • 视觉断点
  • 使用绝地完成交互代码
  • 持续的断点
  • 使用鼠标多线程/多处理支持深度对象检查
  • 远程调试
  • 看表情
  • 在调试器代码版
  • 流行的web服务器集成出错出错
  • 与werkzeug调试器相反,在跟踪期间异常中断(而不是事后分析)
  • 通过代码注入中断当前运行的程序(在受支持的系统上)

它有一个很棒的基于浏览器的用户界面。一种使用的乐趣!:)

在Python代码的相应行中添加import pdb; pdb.set_trace()breakpoint() (python3.7形式)并执行它。执行将在交互式shell中停止。在shell中,您可以执行Python代码(即打印变量)或使用如下命令:

  • c继续执行
  • n步骤到同一函数中的下一行
  • s步骤到该函数或被调用函数的下一行
  • q退出调试器/执行

另见:https://poweruser.blog/setting-a-breakpoint-in-python-438e23fe6b28

从我自己的经验来看,有两种方法:

  1. 使用ipdb,这是一个像pdb一样的增强调试器。

    import ipdb;ipdb.set_trace()breakpoint() (从python3.7)

  2. 使用django shell,只需使用下面的命令。这在您开发新视图时非常有用。

    # EYZ0 < / p >