赋闲脱产的半年里,自己用 C++/Java/Lisp 胡乱写了几万行的代码,到了现在的公司,给 OpenStack 项目贴牛皮藓,反倒是 Python 用得最多。作为公司里面唯一的 Emacser(没准也是公司里 JJ 最长的吧,),我一直致力于在 Emacs 平台上折腾出一套顺手的 Python 开发环境,所幸有些小心得,付诸纸面,以飨大家。

Python.el 的选择

Emacs 的 python-mode 有两套,一个是 Emacs 官方提供的 Python.el,另外一套是 Python 社区提供的 Python-mode.el。不过 Python.el 和 Python-mode.el 都有各种各样的小问题,Python.el 似乎是无法正确处理 Python 的 docstring,而 python-mode.el 的 menu项太过繁杂,而且很多 menu 无法正确工作。这里用到的 python.el 来自于 https://github.com/fgallina/python.el,细节可以参考水木社区的讨论

安装方法可以参考项目主页的 README,我自己针对 el-get 做了一个 recipe,这样以后更新装卸都会方便很多,recipe如下:

(:name python
       :website "https://github.com/fgallina/python.el"
       :description "improved python.el from Fabián Ezequiel Gallina"
       :type github
       :pkgname "fgallina/python.el")

不过这个 patch 并没有被 el-get 接收,限于时间精力,我没有再去细究 el-get 撰写 recipe 的规范。

IPython 集成

交互式的开发是 Python/Ruby/Lisp 这类动态语言的重要特性,它让程序员从“编码 –> 编译 –> 运行 –> 调试”的程序开发工程链中解放出来,从老旧的批处理是开发过渡到现代的交互式开发。如果你用过 SLIME,你就会知道,交互式的开发不仅仅是一种开发模式, SLIME 也不仅仅是一种工具,而是一种编程的革命。Emacs 集成 IPython,虽然没有 SLIME 那么强大,但是对于提高开发效率还是有莫大的帮助的。幸运的是,fgalling/python.el 是支持 IPython 的。关于 fgalling/python.el 的参考设置如下:

(add-to-list 'load-path (expand-file-name
                         "~/.emacs.d/el-get/python"))
(require 'python)
(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))
(setq
 python-shell-interpreter "ipython2"
 python-shell-interpreter-args ""
 python-shell-prompt-regexp "In \\[[0-9]+\\]: "
 python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: "
 python-shell-completion-setup-code
 "from IPython.core.completerlib import module_completion"
 python-shell-completion-module-string-code
 "';'.join(module_completion('''%s'''))\n"
 python-shell-completion-string-code
 "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")

常用快捷键:

  • C-c C-z(python-shell-switch-to-shell) ,切换至 IPython 解释器
  • C-c C-c(python-shell-send-buffer &optional ARG) ,发送整个 buffer 内容到 IPython 解释器运行

Emacs 补全: Pymacs 和 Ropemacs

语言补全一直是 Vim/Emacs 这类上古 “IDE” 的弱项,每种语言都有自己的补全插件、配置方法和版本差异,而网上资料、特别是中文资料,或是陈旧潦草,或是语焉不详,常常让初学者们不知所措。本文所载内容恐怕两年左右就会过时,诸位看官高贤注意鉴别……

Emacs 下的通用补全插件大概就是 auto-completeyasnippet 了,前者可以做出基于 buffer 分词的补全,后者可以基于特定编程语言语法结构的补全。不过基于语义的补全, Emacs + Python下用的是 Pymacs 和 Ropemacs。需要安装的有

  • pymacs
  • rope
  • ropemacs
  • ropemode

以上均可通过 el-get 安装。如若使用过程中出现莫名问题,不要纠缠,有可能是版本问题,无妨试验下用 apt-get/pacman/yum 安装。我本机上的配置如下:

;;; pymacs, rope and ropemacs
(add-to-list 'load-path "~/.emacs.d/el-get/pymacs")
(require 'pymacs)

(setq pymacs-load-path '("~/.emacs.d/el-get/rope"
                         "~/.emacs.d/el-get/ropemacs"))

;; Initialize Pymacs
(autoload 'pymacs-apply "pymacs")
(autoload 'pymacs-call "pymacs")
(autoload 'pymacs-eval "pymacs" nil t)
(autoload 'pymacs-exec "pymacs" nil t)
(autoload 'pymacs-load "pymacs" nil t)
;; Initialize Rope
(pymacs-load "ropemacs" "rope-")
(setq ropemacs-enable-autoimport t)

virtualenv

virtualenv 是 Python 的 sandbox(沙盒)。那么什么是 sandbox 呢?

在日常开发中我们常常碰到这样的场景:

  • 需要针对不同的 Python library 做测试(兼容性、性能等)
  • 需要多人共享一台开发机

可是:

  • 并不是所有人都有向系统 PYTHONPATH 安装 Python library 的权限
  • 我们常常需要同时安装多个不同版本的 Python library

而 virtualenv 通过一些脚本,通过软连接和修改环境变量的方式,提供了一个轻量级的虚拟 Python 环境,在这里面个人可以按照自己意愿任意装卸配置 library,也可以针对不同版本的 library 创建不同的 virtualenv,方便的很。

virtualenvwrapper

virtualenv 默认是在当前目录下建立一个 .venv 目录,但是这样有一个问题,就是 virtualenv 本身的管理很不方便,因为需要记忆不同的 .venv 的存放位置、具体用途等等。 virtualenvwrapper 则通过一些 Python 和 shell 脚本,在 virtualenv 的基础上建立了一层抽象,实现了对 virtualenv 本身的统一管理。virtualenvwrapper 会默认在 $HOME/.virtualenvs 目录下创建所有的 virtualenv。

virtualenv 和 virtualenvwrapper 均可以通过 python pip 安装:

pip install virtualenv virtualenvwrapper

常用命令:

  • mkvirtualenv venv_name – 建立一个新的 virtualenv,
  • workon venv_name – 切换到 venv_name 这个 virtualenv

virtualenv.el

virtualenv.el 可以配合 Emacs 集成 virtualenv,可以通过 el-get 安装。 virtualenv.el需要 virtualenv 和 virtualenvwrapper。

配置:

;; virtualenv support
(add-to-list 'load-path (expand-file-name
                         "~/.emacs.d/el-get/virtualenv"))
(require 'virtualenv)

常用命令:

  • M-x virtualenv-workon – 切换 virtualenv

Miscs

一些 hook 设置:

(add-hook 'python-mode-hook
          (lambda ()
            (ropemacs-mode)
            (global-set-key (kbd "RET") 'newline-and-indent)
            (auto-fill-mode 1)
            (virtualenv-minor-mode 1)))

除了以上,Emacs 中和 Python 开发有关的插件还可以有 pylint、pep8、pyflakes 等,参考文章:

以上,抛砖引玉,希望能够对刚刚接触 Linux/Python/Emacs 的朋友有些许帮助。