每 次重装完系统以后,我都得折腾好长时间,要更新配置文件,要用新版本的软件,要试用新的工具。毕竟这会儿捣鼓东西是最方便的,折腾得无法挽回时大不了再重装呗……
这次将系统升级到Snow Leopard,折腾了良久,终于轮到捣鼓Python环境了。这回要对Python包进行一下管理了。项目多了,难免会有某些包的依赖关系不一致的情 况,如果还和以前那样全部安装到同一个site目录的话,问题还是满大的。最理想的情况是,在系统的site目录里,只装一些基本常用的包,然后各个项目 使用定制的运行环境。这个需求其实挺好实现的,因为我们有Virtualenv!
好像是去年吧,有段时间Django社区中讲述如何使用Virtualenv和fabric部署Django环境的文章大爆发,我也是在那时知道有 Virtualenv这么个好东西,不过由于人懒,也就是试了试,一直没正式用上。这回赶着重装系统,赶紧地好好调教一下,弄个舒适的开发环境:)
Virtualenv的安装很简单,和一般Python包的安装没啥区别。在安装完成以后,使用:
$ virtualenv <env-name>
来建立一个新的运行环境,然后就可以运行:
$ source <env-path>/bin/activate
就可以进入相应的独立环境了,之后就该干嘛干嘛去吧~
Virtualenv使用非常简单,不过本人既然都开始折腾了,为了使用的方便,还是有一些地方需要微调一下的。
首先是ipython的问题,由于ipython的启动脚本默认使用的是调用ipython安装环境的python来执行的,所以各位童鞋可能会发 现在Virtualenv环境下启动ipython后无法调用当前Virtualenv环境安装的软件包。这个问题改起来很简单,要么把ipython的 启动脚本中的第一行改成
#!/usr/bin/env python
或者将ipython定制成别名
alias ipython="python -c 'import IPython; IPython.Shell.IPShell().mainloop()'"
接下来,开始考虑 PYTHONPATH 的问题。默认情况下,Python使用当前目录和系统目录作为包文件的搜索路径,同时提供了 PYTHONPATH 这个变量来自定义额外的搜索路径。咱都用上Virtualenv了,为了方便,何不在进入Virtualenv的时候就直接把需要的目录加进去呢? 其实还是很惊奇Virtualenv默认没有提供这个功能的,不过,这事也简单,改一下启动脚本就可以了
# <env-dir>/bin/activate deactivate () { # ...... # Mandatory for every virtualenv to switch between envs correctly if [[ ${!_OLD_PYTHONPATH[@]} ]]; then PYTHONPATH="$_OLD_PYTHONPATH" export PYTHONPATH unset _OLD_PYTHONPATH fi # ...... } # Optional _OLD_PYTHONPATH="$PYTHONPATH" echo $_OLD_PYTHONPATH PYTHONPATH="<any-python-path-you-want>:$PYTHONPATH" export PYTHONPATH
嗯,这下在进入、退出或者切换Virtualenv的时候就会自动切换 PYTHONPATH 了。
最后一项,纯粹是为了方便管理多个virtualenv了——简化virtualenv的启动命令,并启用bash completion。
基本思路是把所有的env部署在同一个目录下:
~/envs |- env1 |- env2 - env3
这样不同的env之间的只需要通过名称进行区别就可以了。获取了环境名作为特征值,就可以定义如下的bash函数了
ve() { if [[ $1 == */* ]]; then . $1/bin/activate else . $VENVS/$1/bin/activate fi }
这个函数可以接受env路径或者是特征值,然后调用相应的启动脚本启动相应环境。当然,如果要用特征值,别忘了定义 VENVS 这个环境变量
export VENVS=~/envs
至于为我们刚刚定义的 ve 函数启用bash completion,做起来也是简单,只需要对 VENVS 目录下的子目录作名称匹配就可以了
_ve() { COMPREPLY=() if [[ $COMP_CWORD == 1 ]] ; then COMPREPLY=( $(compgen -d $VENVS/${COMP_WORDS[COMP_CWORD]} | sed "s//.*///") ) return 0 fi } complete -F _ve ve
把这段代码存成文件,在 .bashrc 中导入一下,然后就可以开始享受bash completion带来的切换环境的爽快感了。:
$ ve [TAB] proj1 proj2 env1 env2 $ ve p[TAB] proj1 proj2
好了,基本捣鼓完了,目前用着还是挺满意的。不知各位童鞋觉得怎么样?还有啥建议不?