Emacs:调试Python的方法
我之前在 programmers.stackexchange.com 上发过这个问题,但我觉得在这里问可能更合适。
我一直用emacs来编辑代码。通常,我会用 M-x compile 来运行我的测试程序,这样大约能帮我完成70%的工作,让代码保持在正确的轨道上。不过最近我在想,是否可以在某些情况下使用 M-x pdb,这样我就可以设置断点并检查一些东西。
我在网上搜索时发现了一些资料,这些资料表明这可能是有用的或可行的。不过我还没能找到一种我完全理解的方式来让它工作。
我不知道是不是因为 buildout 和 appengine 的组合让事情变得更复杂,但当我尝试做类似下面的事情时:
M-x pdb
Run pdb (like this): /Users/twillis/projects/hydrant/bin/python /Users/twillis/bin/pdb /Users/twillis/projects/hydrant/bin/devappserver /Users/twillis/projects/hydrant/parts/hydrant-app/
这里的 .../bin/python 是 buildout 创建的解释器,路径已经为所有的包设置好了。
~/bin/pdb 是一个简单的脚本,用来调用当前的 python 解释器进入 pdb.main。
HellooKitty:hydrant twillis$ cat ~/bin/pdb
#! /usr/bin/env python
if __name__ == "__main__":
import sys
sys.version_info
import pdb
pdb.main()
HellooKitty:hydrant twillis$
.../bin/devappserver 是 buildout 配方为 GAE 项目创建的 dev_appserver 脚本,而 .../parts/hydrant-app 是 app.yaml 的路径。
我首先看到一个提示:
Current directory is /Users/twillis/bin/
C-c C-f
但什么也没发生,
HellooKitty:hydrant twillis$ ps aux | grep pdb
twillis 469 100.0 1.6 168488 67188 s002 Rs+ 1:03PM 0:52.19 /usr/local/bin/python2.5 /Users/twillis/projects/hydrant/bin/python /Users/twillis/bin/pdb /Users/twillis/projects/hydrant/bin/devappserver /Users/twillis/projects/hydrant/parts/hydrant-app/
twillis 477 0.0 0.0 2435120 420 s000 R+ 1:05PM 0:00.00 grep pdb
HellooKitty:hydrant twillis$
虽然
C-x [space]
会报告说已经设置了一个断点。但我就是无法让它正常运行。
感觉我在这里漏掉了什么明显的东西。难道真的是这样吗?
那么,在 emacs 中进行交互式调试值得吗?在 Google App Engine 应用中进行交互式调试可能吗?有没有什么建议可以让我让这个工作起来?
2 个回答
试着在你的代码里使用 pdb.set_trace()
。然后,不要用你的驱动脚本,直接正常调用你的程序就可以了(我觉得像这样 /Users/twillis/projects/hydrant/bin/devappserver /Users/twillis/projects/hydrant/parts/hydrant-app/
应该就能在你的情况下正常工作)。这样你就可以在调用 pdb.set_trace()
的地方进入调试器,然后你可以在这里添加断点或者做其他需要的操作。
在使用Google App Engine(GAE)时,有一个特别的问题,就是它会把标准输出(STDOUT)重定向到浏览器里,包括调试信息。
根据
的说明,通常的调试流程是在你需要的代码位置设置一个断点。一般情况下,你会写import pdb; pdb.set_trace()
,但是在GAE的情况下,你还需要处理标准输入(STDIN)和标准输出(STDOUT)。比如,下面这段代码:
def set_trace():
import pdb, sys
debugger = pdb.Pdb(stdin=sys.__stdin__,
stdout=sys.__stdout__)
debugger.set_trace(sys._getframe().f_back)
接着在emacs中启动一个shell,然后从那里运行你的代码:
$ ./bin/devappserver /Users/twillis/projects/hydrant/parts/hydrant-app/
为了方便在emacs的shell交互窗口中快速找到合适的位置,我使用了一个叫poptoshell.el的工具(你可以在网上搜索一下,我没有足够的声望来添加链接)。
最后,确保你使用的python-mode版本足够新,以包含pdbtrack功能(你几乎肯定会有这个功能,但你确实需要它,因为它可以让你在emacs中逐步调试代码)。