用 PDB 调试的方法有好几种,我一般就是在需要做断点的地方插入一行(我实际用的是
IPDB —— PDB 的加强版):
import ipdb; ipdb.set_trace()
当然,由于经常用,我在网上找了个 Elisp 函数来避免手敲之苦:
1:(defun python-add-breakpoint ()
2: "Add a break point"
3: (interactive)
4: (newline-and-indent)
5: (insert "import ipdb; ipdb.set_trace()")
6: (highlight-lines-matching-regexp "^[ ]*import ipdb; ipdb.set_trace()"))
7:
8:(define-key python-mode-map (kbd "C-c C-b") 'python-add-breakpoint)
这个函数会插入一行上面提到的 Python 代码,并把其高亮显示。
然后我在 Emacs 中运行 shell,在 shell 中运行 Python 程序,当程序运行到断点的时
候,就会自动进入 PDB。
比如,我有 ~/test.py 这个文件,内容为:
1:#!/usr/bin/env python
2:#-*- encoding: utf-8 -*-
3:#
4:#Author: 任文山 (Ren Wenshan)
5:
6:
7:def f(a, b):
8: return "%d - %d" % (a, b)
9:
10:if __name__ == "__main__":
11: for i in xrange(9, 1, -1):
12: if i == 6: import ipdb; ipdb.set_trace()
13: print f(i, i - 2)
我在第12行设置了一个断点,按 M-x shell 打开一个 shell,在里面运行这个文件:
cd ~ && python test.py
然后就会在 i 等于6的时候进入 PDB:
1:wenshan@debian-vm-home:~$ cd ~ && python test.py
2:9 - 7
3:8 - 6
4:7 - 5
5:> /home/wenshan/test.py(13)()
6: 11 for i in xrange(9, 1, -1):
7: 12 if i == 6: import ipdb; ipdb.set_trace()
8:---> 13 print f(i, i - 2)
9:
10:ipdb>
这个时候,如果想重新定义 f() 这个方法,可以直接在 PDB 里写,但是很不方便,我们
可以通过在 PDB 中执行以下代码进入 Python 的交互式解释器:
!import code; code.interact(local=vars())
同样,作为经常用到的一个功能,我写了一个 Elisp 函数来帮忙:
1:(defun python-interactive ()
2: "Enter the interactive Python environment"
3: (interactive)
4: (progn
5: (insert "!import code; code.interact(local=vars())")
6: (move-end-of-line 1)
7: (comint-send-input)))
8:
9:(global-set-key (kbd "C-c i") 'python-interactive)
这样,在 PDB 中按 C-c i 就进入到交互式解释器了。
现在就可以在交互式解释器中写代码了。
但是,还是不够方便,因为 Python 对缩进要求得非常严格(我又爱又恨的特点),往往
写错一点儿就得重新来过。于是,我想直接在正常的 Python buffer 中写 Python 代码,
然后发送到这个交互式解释器执行。