[python] cx_Oracle 在 virtualenv 中的 pip 安装

cx_Oracle 是 Python 连接 oralce 数据库的库。而这个库并不是个完全独立自主的库,正确安装它还依赖与 oralce 的 instant client。而 InstantClient 又是区分于各个平台的。这样一来,相较于 virtualenv + pip 实现工程的的库管理以及迁移就麻烦许多。

我先实现的是 ubuntu 环境下的配置

# setup virtualenv and activiate
$ virtualenv venv
$ source venv/bin/activate

# download oracle client, from http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html
# instantclient-basic-linux.x64-11.2.0.4.0.zip
# instantclient-sdk-linux.x64-11.2.0.4.0.zip
# unzip oracle client to tools

$ mkdir tools
$ unzip instantclient-basic-linux.x64-11.2.0.4.0.zip -d tools
$ unzip instantclient-sdk-linux.x64-11.2.0.4.0.zip -d tools

# install cx_oracle
# 注意:ORACLE_HOME 要指向绝对路径
$ export ORACLE_HOME=
$ ln -s tools/instantclient_11_2/libclntsh.so.11.1 tools/instantclient_11_2/libclntsh.so
$ ln -s tools/instantclient_11_2/libocci.so.11.1 tools/instantclient_11_2/libocci.so

$ pip install cx_Oracle

完成之后,venv中的python就能正确的 import cx_Oracle。因为下载的的 InstantClient 只是 zip 文件,而且只是解压到本地,所以没有相关文件安装到系统(下的rpm包还要转成deb)。

如果使用 pyinstaller 对工程再进行打包。记得在 spec 文件中加入 libociei.so 文件的包含即可。

coll = COLLECT(
    importer_exe,
    importer_a.binaries,
    importer_a.zipfiles,
    importer_a.datas,
    [
        ("libociei.so", "tools/instantclient_11_2/libociei.so", "BINARY")、
    ],
    ...

蛋疼的情况来了,我的部署环境又是 xp。所以,我还是要在 xp 上重新建起来真个 python 的开发环境。

插点题外话,对于我来说,windows 现在越来越难用了,主要是缺少梯子。而且对于越来越多来历不明的安装文件,安装起来都觉得发毛。另外,其实我对 mingw32 这类的工具包其实也没有什么好感,嵌入了很多 linux 的命令,而用法又各有各的不同。所以在 windows 下,我就基本只用 gitbash + sublimetext就够了。

安装的大致步骤其实是一样的,无非是 venv/bin 换成了 venv/Scripts,InstantClient 的 basic 和 sdk 包还是要下,只不过是换成了 nt 版本。

还有个更大的问题,因为 pip cx_oracle 还是用重新编译的,而 windows 上默认是没有编译器的(话说,有几台linux里面没有gcc呢……),所以会出现“error: Unable to find vcvarsall.bat”错误。其实运行 xp 上的 python 命令,就可以发现 “Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32” 这行简介。其中的 MSC v.1500 就说明当前的 python 是使用 visual c++ 2008 编译的。虽然有一些解决方案是将编译器设置为 mingw32,但是我总是感觉这样似乎还是不够xp。所以,还是下了一个 visual studio 2008 express。只安装其中的 visual c++ 2008就好了。(即便这样,也占用了大概1G的空间,WTF)。安装完成以后,系统会增加一个名为“VS90COMNTOOLS”的环境变量,并指向刚才vc2008的编译器路径。就是通过这个配置,pip在编译的时候就可以找到vc的编译器了,同理。如果已经安装了其它版本的vs,可能没有这个环境变量,可能有“VS100COMNTOOLS”、“VS110COMNTOOLS”这样的环境变量。那么新建一个90的,指向它们就好了。友情提示,在这个过程中,可能需要重新开启终端,好让环境变量生效。

不过即便这样,调用 cx_Oracle 的时候还是可能出错。

>>> import cx_Oracle
Traceback (most recent call last):
  File "", line 1, in 
ImportError: DLL load failed: 找不到指定的模块。

此时,就还需要拷贝 $ORACLE_HOME 文件夹内的 oci.dll, oraociei11.dll 到 venv\Lib\site-packages 内。否则,虽然可以正确import,但是在实际调用中会出现以下错误:

cx_Oracle.InterfaceError: Unable to acquire Oracle environment handle

在 spec 脚本中,与之前添加的那行换成

("oraociei11.dll", "tools\\instantclient_11_2\\oraociei11.dll", "BINARY"),

即可,不过这个dll就有100+M大小,我们自己的程序才多少东西……

至此,cx_Oracle算是能装能用了。会这么麻烦,无非还是因为oracle的闭源架构。cx_Oracle其实也只是给这个 dll 作 python 接口而已。而 oracle 的 server 安装起来就更蛋疼了。centos都要搞半天,而在ubuntu上几乎是装不起来。所以,如果是自己的项目,不管是 mySQL,postgreSQL,都比 Oracle 好用的多,而性能的话,无非就是呵呵了,千万不要被“行业的主流架构”所坑。

关于aGuegu

阿古 真名:官微宏,技术Geek,玩Arduino,玩Linux,爱Google,爱开源;现居福州
此条目发表在python分类目录,贴了, , , , 标签。将固定链接加入收藏夹。