在MacOSX上导入cx_Oracle(Python)
在一个Python脚本中导入cx_Oracle失败了。
我已经安装了cx_Oracle,使用的是“pip install cx_oracle” - 这个过程很顺利,显示已经安装好了。
现在当我尝试:
import cx_Oracle
我遇到了以下错误
Traceback (most recent call last):
File "reader.py", line 9, in <module>
import cx_Oracle
ImportError: dlopen(/Library/Python/2.7/site-packages/cx_Oracle.so, 2): Symbol not found: _OCIAttrGet
Referenced from: /Library/Python/2.7/site-packages/cx_Oracle.so
Expected in: flat namespace
in /Library/Python/2.7/site-packages/cx_Oracle.so
其他信息:
Python版本 2.7 / mac os 10.7.2 (Lion)
$ python
Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
Oracle 10.2
$ sqlplus -version
SQL*Plus: Release 10.2.0.4.0 - Production
另外,我的ORACLE_HOME文件夹里根本没有/bin目录,我只安装了即时客户端和SDK。
ox_Oracle
$ pip freeze
PyRSS2Gen==1.0.0
...
cx-Oracle==5.1.1
(我发现很多关于如何安装cx_Oracle的问题,但没有人问过这个 - 谢谢)
2 个回答
-1
先把所有东西都卸载掉。
然后安装Oracle即时客户端:
接着用pip来安装cx_oracle。
然后设置路径,让它指向Oracle的32位版本。
- 在你的主目录中编辑.profile文件,添加Oracle的bin目录路径,使用这行代码:
- export PATH=$PATH:/usr/local/lib/instantclient/
这样就可以用了……
2
今天我遇到了一个问题,通过把InstantClient二进制文件中引用的库的路径改成实际的文件系统位置,我解决了这个问题。这个博客 http://blog.caseylucas.com/2013/03/03/oracle-sqlplus-and-instant-client-on-mac-osx-without-dyld_library_path/ 提供了详细的解释和调整所有二进制文件的脚本。唯一的问题是,它使用了@executable_path,但在Python 2.7和El Capitan上似乎不再有效(我不太确定是什么导致了这个安全异常)。把@executable_path替换成实际路径就可以正常工作了。
总结一下,让它正常工作的步骤:
- 把InstantClient安装到 /usr/local/instantclient_11_2
- 确保你使用的cx_Oracle.so共享对象在 /Library/Python/2.7/site-packages/cx_Oracle.so 这个位置
把下面的脚本复制到 /usr/local/instantclient_11_2
#!/bin/sh # script to change the dynamic lib paths and ids for oracle instant client # exes and libs (echo /Library/Python/2.7/site-packages/cx_Oracle.so ; find . -maxdepth 1 -type f \( -perm -1 -o \( -perm -10 -o -perm -100 \) \) -print ) | while read exe do echo adjusting executable $exe baseexe=`basename $exe` otool -L $exe | awk '/oracle/ {print $1}' | while read lib do echo adjusting lib $lib baselib=`basename $lib` if [ "$baseexe" = "$baselib" ] then echo changing id to $baselib for $exe install_name_tool -id $baselib $exe else echo changing path id for $lib in $exe install_name_tool -change $lib /usr/local/instantclient_11_2/$baselib $exe fi done done
- 用管理员权限运行这个脚本。