12

尝试导入 cx_Oracle 时出现标准的“DLL 加载失败;找不到模块”错误。我安装了正确的即时客户端,路径都正确...运行 Dependency Walker 告诉我我缺少以下 .dll 的 MSVCR90、GPSVC、IESHIMS。

我正在为 Oracle 11g 和 Python 2.7 运行即时客户端。有人有想法么?我发现的大多数答案都包含不正确的路径,但似乎并非如此……此外,我在系统的其他任何地方都找不到这些 .dll 中的任何一个。

编辑:我最终安装了 Oracle XE 11g(32 位);Python 2.7 和 cx_Oracle 也是 32 位的(我还应该补充一点,我在 Windows 上)。cx_Oracle 现在安装干净;但是在连接时我收到一个错误:

InterfaceError: Unable to acquire Oracle environment handle

ORACLE_HOME 路径正确,PATH 文件夹中的 bin 也是正确的...

4

5 回答 5

8

您运行的是哪个版本的 Windows?它是 32 位还是 64 位?

您的 Oracle Instant Client 是32位还是64位?

你的 Python 安装是32位还是64位?

你的 cx_oracle 是正确的版本吗?32位还是64位?

MSVCR90.dll 是 Microsoft Visual C++ 2008 SP1 Redistributable 包的一部分。

这里有 32 位版本,这里有64 位版本。

如果您C:\Program Files\Internet Explorer\Ieshims.dll的版本为Windows 是 Vista 或更新版本。

GPSVC.dll 应该存在于C:\Windows\System32.

Dependency Walker 将最后 2 个 DLL 报告为缺失,因为 Windows 错误报告使用 IEFrame.DLL 并延迟加载,这意味着它们可能永远不会真正需要。

我发现为了让 cx_oracle 干净地导入,您需要确保其依赖项的版本匹配。您还需要确保 Oracle 客户端安装与您匹配ORACLE_HOME,并且您的 PATH 变量包含%ORACLE_HOME%/bin设置为环境变量或在注册表中,并且您的 tnsnames.ora 文件位于 TNS_ADMIN 设置的值中。正如Emmanuel的回答中所述,未设置的 TNS_ADMIN 设置的默认值为%ORACLE_HOME%\network\admin.

除非绝对必要,否则我也很少使用 oracle 安装程序的即时客户端版本,因为与其他版本不同,它不会始终确保正确设置或维护路径、ORACLE_HOME 或 TNS_ADMIN,这会导致 tnsnames.ora 和 OCI.dll 不存在成立。当您在同一台机器上有多个 Python 版本或 Oracle 版本时,这会变得更加复杂。

要显式设置它们,您可以使用环境变量(用户或系统),它们位于控制面板中的系统图标、高级系统设置任务、高级选项卡、环境按钮下。

关于InterfaceError: Unable to acquire Oracle environment handle,这特别发生在与不解析 OCI.dll 相对的情况下,cx_Oracle 不知道要使用哪个 OCI.dll,通常是这种情况,因为 PATH 变量包含两个或多个包含 OCI.dll 的搜索目录。

特别是确保您的 PATH 仅包含来自即时客户端安装或 Oracle 11G XE 安装的一个即时 OCI.dll 应该可以解决您的问题。

您是否在安装 Oracle 11G XE 之前卸载了即时客户端?

将以下内容粘贴到命令提示符中。

echo The current ORACLE_HOME is %ORACLE_HOME%

echo The current TNS_ADMIN is %TNS_ADMIN%

echo The current PATH is %PATH%

查看这些变量的当前值。

更多资源

于 2012-11-27T19:07:42.927 回答
4

我遇到了同样的问题:您必须设置变量ORACLE_HOME以匹配您的 Oracle 客户端文件夹(在 Unix 上:例如通过 shell;在 Windows 上:如果配置面板的环境变量中不存在新变量,则创建一个新变量)因为这是cx_Oracle模块可以链接到它的方式。

您的文件夹$ORACLE_HOME/network/admin%ORACLE_HOME%\network\admin在 Windows 上)是您的tnsnames.ora文件应该存在的地方。

于 2012-11-27T18:42:24.560 回答
1

更新 06.10.2020

出于安全原因,MacOS DYLD_LIBRARY_PATH 似乎未设置:

生成受系统完整性保护限制的进程的子进程,例如通过在与 NSTask 的捆绑中启动辅助进程或调用 exec(2) 命令,重置该子进程的 Mach 特殊端口。启动受保护进程时会清除任何动态链接器 (dyld) 环境变量,例如 DYLD_LIBRARY_PATH。

几种可能的解决方案:

  • 将脚本中的 shebang 行从 env (eg #!/usr/bin/env python2.7) 替换为 python ( #!.../venvs/project11/bin/python2.7),如下所述
  • 在调用 python 脚本的脚本中设置 DYLD_LIBRARY_PATH
  • 像这样调用脚本:DYLD_LIBRARY_PATH=... <script-to-run>
  • 在 shell(.bash_profile 或类似)中设置 DYLD_LIBRARY_PATH 并使用source/. <script-to-run>

较早的分析

我在我的案例中发现如下:

  • 可重定位模式下的 virtualenv 设置 (--relocatable) 使用/usr/bin/env实用程序作为django-admin.py 的shebang

    #!/usr/bin/env python2.7
    
  • env是编写可在各种n x 环境中运行的 unix 脚本的便捷实用程序

  • 在 OSX(我使用的是 macos 10.12 Sierra)上,出于某种原因/usr/bin/env 隐藏了一些在父进程中可见的系统变量- 在这种情况下,DYLD_LIBRARY_PATH不会转移到子进程。测试:

    set|grep DYLD_LIBRARY_PATH
    DYLD_LIBRARY_PATH=.../oracle/instantclient_11_2
    
    env|grep DYLD_LIBRARY_PATH
    # nothing
    
  • 再检查一次::

    python -c "import os; print os.environ.get('DYLD_LIBRARY_PATH')"
    .../instantclient_11_2:/usr/local/opt/openssl/lib
    
    # put the same line in first line of django-admin.py 
    # and you will get no output for DYLD_LIBRARY_PATH 
    
  • 有趣的是,在 Linux(例如 CentOS)上,情况并非如此,DYLD_LIBRARY_PATH 和 LD_LIBRARY_PATH 在子进程中可见

  • 由于这个 cx_oracle.so 无法加载所需的 oracle 库,它失败并出现错误:

    Unable to acquire Oracle environment handle
    

解决方案是在 django-admin.py 中更改 shebang:

  • 从:

    #!/usr/bin/env python2.7
    
  • 类似于(检查您的python venv安装:哪个python):

    #!.../venvs/project11/bin/python2.7
    
  • 它也像这样工作 - 但不如以前的解决方案灵活::

    #!/usr/bin/env DYLD_LIBRARY_PATH=<put-full-path->/instantclient_11_2 python2.7
    
  • 或者在使用 cx_Oracle 或任何其他 DYLD_LIBRARY_PATH 依赖模块时,最简单的方法是不要在 OSX 中使用可重定位的 virtualenv 设置

于 2016-12-19T09:14:00.040 回答
0

我记得不得不把它弄得一团糟才能让它工作。在我.bash_profile运行 Oracle XE 的系统上,我有:

export ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server
export SID=XE
export LD_LIBRARY_PATH=$ORACLE_HOME:$ORACLE_HOME/lib
export PATH=$PATH:$ORACLE_HOME/bin
于 2016-03-24T22:21:15.680 回答
-1

也许您可以将所有带有“.dll”扩展名的文件复制到 Python 的安装路径中,例如“%python_home%\Lib\site-packages”。

于 2017-05-07T07:25:14.647 回答