在Emacs中使用当前虚拟环境的Python进程调试pdb
我在用Emacs调试一些Python代码,使用的是pdb,但遇到了一些导入的问题。我的依赖库安装在一个我自己设置的虚拟环境里。
但是,pdb偏偏使用的是/usr/bin/python,而不是我虚拟环境里的Python。
我用virtualenv.el来支持在Emacs中切换环境,并通过一些后激活的钩子来实现,具体可以参考这篇文章:
http://jesselegg.com/archives/2010/03/14/emacs-python-programmers-2-virtualenv-ipython-daemon-mode/
在运行M-x python-shell时,这个方法效果很好。
>>> import sys
>>> print sys.path
这指向了我所有虚拟环境的库,表明python-shell确实是我虚拟环境里的。
但是,M-! which python却给出了/usr/bin/python,这就和之前的结果矛盾了。
有没有人知道我该如何让M-x pdb使用当前激活的虚拟环境里的Python进程呢?
4 个回答
可能你的 pdb 命令是和某个特定版本绑定在一起的。
$ ls -ald /usr/bin/pdb
lrwxrwxrwx 1 root root 6 Jun 2 23:02 /usr/bin/pdb -> pdb2.6
接着,看看 pdb2.6 的第一行。它包含了
#! /usr/bin/python2.6
这就是为什么 pdb 总是很固执,似乎总是在某个特定版本的 Python 下运行。因为它确实是这样!实际上,这种依赖关系对于像符号调试器这样的软件来说是有道理的。
我从源代码编译了 python2.7,但显然没有找到 pdb。经过仔细检查,我在 lib 文件夹下找到了 python-2.7 的 pdb.py。
为了方便,我为它创建了一些符号链接:
$ cd /opt/python-dev ##-- this is where I installed from sources
$ cd bin
$ sudo ln -s ../lib/python2.7/pdb.py pdb2.7
$ sudo ln -s pdb2.7 pdb
现在观察 pdb2.7 的第一行。它写着:
#! /usr/bin/env python
... 这看起来比之前的版本要好。它基本上意味着 pdb 将在你环境中定义的当前 Python 下启动,无论是什么,而不是像 /usr/bin/python 或 /usr/bin/python2.6 这样的硬编码路径。知道这一点真不错!
我还从系统文件中删除了 pdb 和 pdb2.6,因为我更喜欢在 virtualenv 中进行开发和调试。这样做的话,我就不会再被同样的把戏所困扰了。
希望这对你有帮助。
这样调用 pdb:
python -m pdb myscript.py
而不是这样:
pdb myscript.py
python-shell
使用一个叫 python-default-interpreter
的变量来决定用哪个 Python 解释器。当这个变量的值是 cpython
时,它会查看另外两个变量 python-python-command
和 python-python-command-args
来确定要使用的解释器和参数。这两个变量是通过 virtualenv.el
来设置当前的虚拟环境的。
所以,当你使用 python-shell
命令时,它会毫无问题地使用你的虚拟环境。
但是,当你输入 M-! python
时,你并没有使用 python-python-command
和 python-python-command-args
这两个变量。因此,它会使用在你的路径中找到的 Python 工具。
当你调用 M-x pdb
时,它会使用 gud-pdb-command-name
作为默认的 pdb 工具。如果你想重新定义这个变量,每次激活环境时可以这样做:
(defadvice virtualenv-activate (after virtual-pdb)
(custom-set-variables
'(gud-pdb-command-name
(concat virtualenv-active "/bin/pdb" ))))
(ad-activate 'virtualenv-activate)
要在你的虚拟环境中使用 pdb,请执行以下操作:
cp /usr/bin/pdb /path/to/virtual/env/bin
然后编辑 /path/to/virtual/env/bin/pdb 的第一行,使其变为:
#! /usr/bin/env python
重新激活你的环境,Pdb 现在应该会使用你的虚拟环境中的 Python,而不是系统全局的 Python。