如何在Django中调试好方法?

时间:2009-07-13 07:57:03

标签: python django debugging

所以,我开始学习Python及以后Django的代码。第一次很难看回溯并实际弄清楚我做错了什么以及语法错误在哪里。现在已经过了一段时间,并且在某种程度上,我想我在调试我的Django代码时有一个例程。由于这是在我的编码经验的早期完成的,我坐下来想知道我是如何做到这一点是无效的,可以更快地完成。我通常设法找到并纠正我的代码中的错误,但我想知道我是否应该更快地完成它?

我通常只使用Django启用时提供的调试信息。当事情最终按照我的想法结束时,我会在语法错误的情况下破坏代码流,并查看流程中该点的变量以找出代码,其中代码执行的操作不是我想要的。< / p>

但这可以改善吗?是否有一些好的工具或更好的方法来调试Django代码?

27 个答案:

答案 0 :(得分:496)

有很多方法可以做到这一点,但最简单的方法就是简单地完成 使用Python debugger。只需将以下行添加到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,那么您还需要查看使用IPDB进行调试的ipython

pdb的一些更有用的扩展是

pdb++建议

Antash

pudb建议

PatDuJour

Using the Python debugger in Django建议

Seafangs

答案 1 :(得分:220)

我非常喜欢Werkzeug的交互式调试器。它与Django的调试页面类似,只是在每个级别的回溯上都有一个交互式shell。如果您使用django-extensions,则会获得runserver_plus管理命令,该命令启动开发服务器并为您提供Werkzeug的异常调试程序。

当然,您应该只在本地运行它,因为它为任何拥有浏览器的人提供了在服务器上下文中执行任意python代码的权限。

答案 2 :(得分:157)

模板标签快一点:

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

现在,在模板中,您可以{{ template_var|pdb }}进入pdb会话(假设您正在运行本地开发服务器),您可以在其中检查element内容。

这是一种非常好的方式来查看对象到达模板时发生了什么。

答案 3 :(得分:80)

有一些工具可以很好地协作,可以使您的调试任务更容易。

最重要的是Django debug toolbar

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

Firebug本身对于调试您开发的任何应用程序的Javascript方面也很关键。 (假设你当然有一些JS代码)。

我也喜欢django-viewtools使用pdb以交互方式调试视图,但我没有那么多使用它。

还有更多有用的工具,如推土机,用于追踪内存泄漏(此处还提供了其他有关内存跟踪的建议的好建议。)

答案 4 :(得分:58)

我使用PyCharm(与eclipse相同的pydev引擎)。真的帮助我在视觉上能够逐步完成我的代码,看看发生了什么。

答案 5 :(得分:42)

到目前为止,几乎所有内容都已被提及,所以我只会添加pdb.set_trace()而不是pip install ipdb可以使用 ipdb.set_trace()来使用iPython,因此功能更强大(自动完成)和其他好东西)。这需要ipdb包,因此您只需要{{1}}

答案 6 :(得分:33)

我已将django-pdb推送到PyPI。 这是一个简单的应用程序,这意味着每次要打破pdb时都不需要编辑源代码。

安装只是......

  1. pip install django-pdb
  2. 'django_pdb'添加到您的INSTALLED_APPS
  3. 您现在可以运行: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主持,当然欢迎提供。

答案 7 :(得分:21)

调试python的最简单方法 - 特别是对于习惯于Visual Studio的程序员 - 使用的是PTVS(Visual Studio的Python工具)。 步骤很简单:

  1. http://pytools.codeplex.com/
  2. 下载并安装
  3. 设置断点并按F5。
  4. 您的断点被点击,您可以像调试C#/ C ++程序一样轻松查看/更改变量。
  5. 这就是全部:)
  6. 如果要使用PTVS调试Django,则需要执行以下操作:

    1. 在项目设置 - 常规选项卡中,将“启动文件”设置为“manage.py”,这是Django程序的入口点。
    2. 在项目设置 - 调试选项卡中,将“脚本参数”设置为“runserver --noreload”。关键点在于“--noreload”。如果您没有设置它,您的断点将不会被击中。
    3. 享受它。

答案 8 :(得分:16)

我在Eclipse中使用pyDev非常好,设置断点,步入代码,查看任何对象和变量的值,尝试一下。

答案 9 :(得分:11)

我使用PyCharm并一直支持它。它花了我一点但我不得不说我摆脱它的优势是无价的。我尝试从控制台进行调试,我确实给了很多人可以做到这一点的功劳,但对我来说,能够直观地调试我的应用程序是很棒的。

我不得不说,PyCharm确实需要大量记忆。但话说回来,生活中没有任何好处是免费的。他们刚刚推出了最新版本3.它还与Django,Flask和Google AppEngine配合得很好。总而言之,我认为这对任何开发者来说都是一个非常方便的工具。

如果您还没有使用它,我建议您试用30天的试用版来了解PyCharm的强大功能。我确信还有其他工具可供选择,例如Aptana。但我想我也喜欢PyCharm的样子。我觉得在那里调试我的应用程序非常舒服。

答案 10 :(得分:9)

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

  1. 有些东西引发了异常runserver_plus'Werkzeug调试程序。在所有跟踪级别运行自定义代码的能力是一个杀手。如果你完全陷入困境,只需点击一下即可创建一个Gist分享。
  2. 页面已呈现,但结果错误:再次,Werkzeug摇滚。要在代码中创建断点,只需在要停止的位置键入assert False即可。
  3. 代码运行错误,但快速查看无济于事。最有可能的是算法问题。叹。然后我通常会启动一个控制台调试器PuDBimport pudb; pudb.set_trace()。与[i] pdb相比的主要优点是PuDB(看起来像80年代一样)使得设置自定义手表表达变得轻而易举。使用GUI,调试一堆嵌套循环要简单得多。
  4. 啊,是的,模板的困境。最常见的(对我和我的同事)问题是错误的上下文:要么您没有变量,要么您的变量没有某些属性。如果您正在使用debug toolbar,只需检查“模板”部分中的上下文,或者,如果这还不够,请在填写上下文后立即在视图代码中设置中断。

    就这样。

答案 11 :(得分:9)

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

import IPython; IPython.embed()

IPython.embed()启动一个IPython shell,它可以从您调用它的位置访问本地变量。

答案 12 :(得分:6)

我刚刚找到了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调试器的非常有用的文章: https://zapier.com/engineering/debugging-python-boss/

最后,如果你想在Django中看到你的调用堆栈的精美图形打印输出,结帐: https://github.com/joerick/pyinstrument。只需将pyinstrument.middleware.ProfilerMiddleware添加到MIDDLEWARE_CLASSES,然后将?profile添加到请求URL的末尾以激活探查器。

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

答案 13 :(得分:6)

我强烈推荐使用epdb(Extended Python Debugger)。

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实例,可以指定要侦听的端口(默认为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())执行与接受的答案相同的操作,但我想强调服务功能,因为我发现它非常有用。

答案 14 :(得分:4)

我使用PyCharm和不同的调试工具。还有一个很好的文章设置为新手轻松设置这些东西。 You may start here.它讲述了一般的Django项目的PDB和GUI调试。希望有人能从中受益。

答案 15 :(得分:3)

调试Django代码的最佳选择之一是通过wdb: https://github.com/Kozea/wdb

  

wdb适用于python 2(2.6,2.7),python 3(3.2,3.3,3.4,3.5)和pypy。更好的是,可以使用在python 3上运行的wdb服务器调试python 2程序,反之亦然,或调试在计算机上运行的程序,其中调试服务器在第三台计算机上的网页内的另一台计算机上运行!   即便是更好的,现在可以使用来自Web界面的代码注入来暂停当前运行的python进程/线程。 (这需要启用gdb和ptrace)   换句话说,它是一个非常强大的pdb版本,直接在浏览器中提供了很好的功能。

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

import wdb
wdb.set_trace()

据作者说,与pdb的主要区别在于:

  

对于那些不了解该项目的人来说,wdb是一个像pdb一样的python调试器,但它具有灵活的Web前端和许多其他功能,例如:

     
      
  • 源语法突出显示
  •   
  • 视觉断点
  •   
  • 使用jedi完成交互式代码
  •   
  • 持续断点
  •   
  • 使用鼠标多线程/多处理支持进行深层对象检查
  •   
  • 远程调试
  •   
  • 观看表达
  •   
  • 在调试器代码版本中
  •   
  • 流行的Web服务器集成以突破错误
  •   
  • 例如,与werkzeug调试器相反,在跟踪期间(非事后验证)异常中断
  •   
  • 通过代码注入打破当前正在运行的程序(在支持的系统上)
  •   

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

答案 16 :(得分:2)

大多数选项都已提及。 为了打印模板上下文,我为此创建了一个简单的库。 见https://github.com/edoburu/django-debugtools

您可以使用它来打印模板上下文而不使用任何{% load %}构造:

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

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

答案 17 :(得分:2)

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

如果没有,请考虑使用它。

答案 18 :(得分:2)

我发现Visual Studio Code对于调试Django应用程序非常棒。标准的python launch.json参数在附加调试器的情况下运行python manage.py,因此您可以根据需要设置断点并逐步执行代码。

答案 19 :(得分:2)

对于那些可能会意外地将pdb添加到实时提交中的人,我可以建议#Koobz的这个扩展回答:

@register.filter 
def pdb(element):
    from django.conf import settings
    if settings.DEBUG:    
        import pdb
        pdb.set_trace()
    return element

答案 20 :(得分:2)

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

  • c继续执行
  • n步入同一功能中的下一行
  • s步入此函数的下一行或调用函数
  • q退出调试器/执行

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

答案 21 :(得分:1)

我强烈建议使用PDB。

import pdb
pdb.set_trace()

您可以检查所有变量值,进入函数等等。 https://docs.python.org/2/library/pdb.html

检查所有类型的请求,响应和命中数据库。我正在使用django-debug-toolbar https://github.com/django-debug-toolbar/django-debug-toolbar

答案 22 :(得分:1)

正如在这里的其他帖子中所提到的 - 在代码中设置断点并通过代码行走以查看它是否像您期望的那样行为是一种很好的方式来学习像Django之类的东西,直到你很好地了解它的行为 - 并且你的代码在做什么。

要做到这一点,我建议使用WingIde。就像其他提到的IDE一样好用且易于使用,漂亮的布局以及易于设置的断点评估/修改堆栈等。完美可视化您的代码在您逐步完成时所做的工作。我是它的忠实粉丝。

我也使用PyCharm - 它具有出色的静态代码分析功能,可以帮助您在发现问题之前发现问题。

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

虽然没有明确的调试或分析工具 - 我最喜欢的是 SQL打印中间件,可从Django Snippets https://djangosnippets.org/snippets/290/

获取

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

我发现在开发和调试我的应用程序时,密切关注查询性能是非常宝贵的。

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

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

答案 23 :(得分:0)

另外一个建议。

您可以一起使用 nosetests pdb ,而是手动在视图中注入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 选项:

tests$ nosetests test_urls_catalog.py --pdb

一旦我遇到任何异常(包括优雅处理的异常),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字段构造函数的选择参数是列表中的列表,而不是元组的列表/元组。

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

巧妙的是,这个pdb是在脆弱的代码中进行的,而不是我的代码,我不需要手动插入它。

答案 24 :(得分:0)

使用pdbipdb。这两者之间的差异是ipdb支持自动完成。

for pdb

import pdb
pdb.set_trace()

for ipdb

import ipdb
ipdb.set_trace()

要执行新行命中n键,请继续按c键。 使用help(pdb)

查看更多选项

答案 25 :(得分:0)

在开发过程中,添加快速

assert False, value

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

答案 26 :(得分:0)

根据我自己的经验,有两种方式:

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

    import ipdb;ipdb.set_trace()breakpoint() (来自python3.7)

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

    python manage.py shell