virtualenv是个好东西,可以为各个Python应用建立各自独立的虚拟环境,对于开发和部署都是很有用的。特别是增强版的virtualenvwrapper,好用到爆。
但是它也会带来很妖蛾子的问题。比如之前我就曾经碰到过这样的问题:
题外话:Mac OS X 10.6 Snow Leopard 下 virtualenv 发生 install_name_tool 错误在Mac OS X 10.6 SL下创建virtualenv失败,报一个install_name_tool错误。搜了很久都没有找到可行的解决方案——所有的解决方案都指向一个:
安装最新版的XCode或其简化版的Command Line Tools包,但是最新版的XCode或CLT都需要系统升级到10.7.3 Lion以上…
虽然最新的10.8 ML也就卖128块,只是我是很不喜欢升级系统的,虽然OS X的升级据说是很平滑的,但保险起见还是需要备份什么的,而且系统升级完会有很多应用也要跟着升级,总之是麻烦。之前用Ubuntu 10.04足足用了两年,一直等到下一个LTS 12.04出来才换掉。而且有很多人升级到ML后都反映速度慢了很多,搞得我就更加不想升了。
后来总算有人说不安装最新的XCode也可以,只要升级到当前系统支持的最高版本XCode即可,于是我花了一个下午时间把SL上能用的最高版本XCode 3.2.6下载来安装了一下才总算解决。
当 virtualenv 遇上非纯 python 包一般来说纯python的包在virtualenv里安装是完全没有问题的,不论是用easy_install还是用pip都很方便。顺便说一句,个人比较推荐用pip,比easy_install好用很多。
问题就在于非纯python包,这种情况通常会需要编译一些C或C++代码来生成一些库。对于非virtualenv来说通常也没啥麻烦的,比如Debian/Ubuntu可以找到相应的apt包来安装,FreeBSD通常也有相应的Ports包可以安装。
但是当virtualenv遇上非纯python包,问题就来了。
相对来说Debian/Ubuntu下还会略好一些,无非是需要先在主环境里安装一些dev包而已,之后在virtualenv里用pip/easy_install安装时就可以自动编译安装了。
对于FreeBSD来说,情况就要麻烦一些了,因为用Ports安装本来就是源码编译的,所以没有另外的dev包可装,因此需要解决一些路径问题才能顺利编译。
其实这个问题我之前也碰到过,也解决了,只是这次再碰到怎么也想不起来上次是怎么解决的,折腾了好长时间,所以还是记下来备查为好。
至于说为什么以上只讨论了Linux/FreeBSD/Mac OS X,没有提到 Windows 呢?那当然是因为:珍爱SM,远离MS。在Windows下用virtualenv基本上跟找死差不多,很多问题根本没有解决方案…
FreeBSD 9 的 virtualenv 里安装 pysqlite 错误首先来看pysqlite。
其实本来Python 2.5以上就内置了对sqlite的支持,但是因为我一直是用sqlalchemy,它是用这个库的,所以还是需要安装一下。
直接在 virtualenv 里用:
pip install pysqlite的话会报编译错误,找到不 sqlite3.h 这个头文件。
解决方法是:
workon yourenv pip install --no-install pysqlite # 这是 virtualenvwrapper 的命令,如果是 virtualenv 请直接用 cd 命令去相应的路径下 cdvirtualenv build/pysqlite vim setup.cfg # 把其中include_dirs和library_dirs两个路径的注释去掉,保存退出后重新安装 pip install pysqlite即可。
FreeBSD 9 的 virtualenv 里安装 gevent 错误方法与上面的类似,不过这次不用修改什么文件,而是直接在build里去安装。
workon yourenv pip install --no-install gevent # 这是 virtualenvwrapper 的命令,如果是 virtualenv 请直接用 cd 命令去相应的路径下 cdvirtualenv build/gevent # 下面这个是我这里的 libevent 所在的 Ports 位置,请根据你自己的情况修改 python setup.py install --libevent /usr/ports/devel/libevent/work/libevent-1.4.14b-stable # 下面这句只是为了做一些安装后的收尾工作,比如清除build目录内容等 pip install gevent即可。