注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

哈欠涟涟的博客

学习python、pyqt与django

 
 
 

日志

 
 

调试django  

2010-02-10 20:12:37|  分类: django |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

原文参考:http://simonwillison.net/2008/May/22/debugging/

一、最大限度地利用error page
    Django的默认error page是值得注意的,它给局部变量提供了详细的踪迹,问题周边的代码,还提供文本描述的异常发email给同事,也可以发送到http://dpaste.com以求帮助。它会显示application的settings,从request得到的GET,POST与COOKIE数据,从HTTP环境中装配的所有重要的META字段。
    在任何view中触发error page的一个技巧是加入下面的代码:
    assert False
    也可在断言中提供一个表达式:
    assert False, request.GET
    当你创建一个复杂form时,它正有用武之地。如你想要看到submit后的数据,可以在view放入assert False,使用error page来检视数据。
二、在开发服务器的console中输出信息
                    如想要知道view中到底发生了什么,最方便的方法是加入print语句。在开发服务器中会把所有的print语句结果输出到终端。
    如想要使用更复杂的logging,不妨试试python的logging模块。在settings.py如下配置:
    import logging
    logging.basiConfig(
        level = logging.DEBUG,
        format = '%(asctime)s %(levelname)S %(message)s',
    )
   
    view中使用方法:
    def my_view(request):
        imort logging
        logging.debug("A log message")
        ...
       
    当开发服务器运行时,log会输出到终端。如果要把log输出到文件中,可以如下操作:
    logging.basicConfig(
        level = logging.DEBUG,
        format = '%(asctime)s %(levelname)S %(message)S',
        filename = '/tmp/myapp.log',
        filemode = 'w'
    )
   
    你能使用tail -f /tmp/myapp.log来实时看到加到log文件中的日志。这个方法即可用于开发过程中,也可用于实际运行过程中。
    一个函数在不同地方多次调用,但只有特别情形下才会出错,这类错误处理时常要遇到。此时你可以使用trackback模块,记录当时的栈,从而知道发生错误时函数的调用情况:
    import logging,trackback,pprint
    def my_buggy_function(arg):
        ...
        if error_condition:
            stack = pprint.pformat(trackback.extract_stack())
            logging.debug('An error occurred: %s' % stack)
   
    由trackback.extract_stack()返回的元组包含了行号,函数名称与python文件的路径,所以你使用它重建程序提供了大量的信息。

三、使用调试器
    在我的调试工具箱中最强大的武器是python的调试器:pdb。这是一个标准库,无需另外安装。pdb是一个命令行调试器。有许多方法可以激活pdb,但最直接的方法是在django视图函数中插入如下代码:
    import pdb; pdb.set_trace()
   
    如在浏览器中浏览这个页面时,浏览器会挂起。开发服务器停止运行,出现了pdb调试界面。
    常用的pdb命令:
    list: 显示运行点周围的源代码。可以多次执行这个命令以增加显示源码的数量。
    n:  执行下一行程序
    s:  与n类似,但进入调用的任何函数。
    r:  继续运行直到当前函数返回
    u:  加到上一层堆栈。所以你可以看到是哪一个函数调用当前函数。
    d:  又回到下一层堆栈。
    locals():   不是pdb命令,但方便看到当前所有变量。
   
    pdb模式下,完全可以作为python交互shell,你不仅可以存取变量,并且可以修复变量的值,调用函数,做你想做的事。而此时浏览器仍然等待在那时,等待HTTP request的返回。如果你按下“c",程序将继续运行,request将被传达,浏览器得到运行结果。
    你不必使用pdb而冻结开发服务器,pdb也可以在交互模式下运行良好。如有一个buggy函数,控测的一个方法是在交互模式下运行它,使用下面的方式:
    >>> def function_that_raises_an_exception():
    ...  assert False
    ...
    >>> function_that_raises_an_exception()
    Traceback (most recent call last):
     File "<stdion>", line 1, in <module>
     File "<stdin>", line 2, in function_that_raises_an_exception
  AssertionError
 >>> import pdb; pdb.pm()
 > <stdin>(2)function_that_raises_an_exception()
 (Pdb)
 
 pdb.pm()容许事后检验,有一个最让人喜爱的特性,它可以让跳回到最近抛出异常地方,即使你抛出异常时没有导入pdb.
 pdb最后一个技巧:可以使用它来调试python命令行脚本,如django的自定义./manage.py命令。按如下方式来做:
 python -i manage.py buggy_command
 
 运行一个脚本后,参数-i可使python进入交互模式。如果脚本触发了一个异常,你可以使用pdb.pm()来进行调试。
四、在生产服务器下处理错误
 在生产模式下django的一个默认行为(DEBUG=False)是给ADMINS中列出的所有人发送email,报告异常。你也能通过设置SEND_BROKEN_LINK_EMAILS,开启每当发生404错误时给所有MANAGEERS的地址发送email报告错误。
  在高流量的网站中,不必为所有服务器错误发送email。一个简洁的方案是使用django-db-log,它把所有异常记录到数据库中。使用MD5 hash统计同一类error报告的次数。
  
  更多有用的中间件
  
  ProfilerMiddleware: 增加?prof到任何url的结尾部分,以查看相对request Python cProfile模块运行的输出。
  DebugFooter:增加一个页脚,显示模板从何处装载、每一个有效的SQL查询及所化的时间。
  
五、使用test client
 最后一个探索应用程序技巧是使用django的TestClient。尽管设计用于单元测试,这个工具在交互模式下还是非常有用的。它能让你用代码来模拟in-process request。代码如下:
 >>> from django.test.client import Client
 >>> c = Client()
 >>> response = c.get("/") # The homepage
 >>> response
 <django.http.HttpResponse object at 0x2300470>
 >>> print response
 Vary: Cookie
 Content-Type: text/html; charset=utf-8
 
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
     "http://www.w3.org/TR/html4/strict.dtd">
 <html>
 ...
 
 response对象是从视图返回的HttpResponse,可以交互查看它的具体情况。
 另一个来自单元测试工具箱的函数能帮助控查一个应用程序:setup_test_environment().如下:
 >>> from django.test.utils import setup_test_environment
 >>> setup_test_environment()
 >>> from django.test.client import Client
 >>> c = Client()
 >>> response = c.get("/")
 >>> response.template
 [<django.template.Template object at 0x2723dd0>,
  <django.template.Template object at 0x2723f30>,
  <django.template.Template object at 0x273ee10>]
 >>> response.context
 [ list of Context objects ]
 
 这让不单可以查看从视图中返回的HTML,还有template与contexts。

  评论这张
 
阅读(1744)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017