Emacs:调试Python的方法

7 投票
2 回答
779 浏览
提问于 2025-04-16 09:06

我之前在 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 个回答

1

试着在你的代码里使用 pdb.set_trace()。然后,不要用你的驱动脚本,直接正常调用你的程序就可以了(我觉得像这样 /Users/twillis/projects/hydrant/bin/devappserver /Users/twillis/projects/hydrant/parts/hydrant-app/ 应该就能在你的情况下正常工作)。这样你就可以在调用 pdb.set_trace() 的地方进入调试器,然后你可以在这里添加断点或者做其他需要的操作。

4

在使用Google App Engine(GAE)时,有一个特别的问题,就是它会把标准输出(STDOUT)重定向到浏览器里,包括调试信息。

根据

pdb文档

的说明,通常的调试流程是在你需要的代码位置设置一个断点。一般情况下,你会写 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中逐步调试代码)。

撰写回答