将加载dll的行为恢复到python 3.8之前和新的add_dll_directory()

问题描述 投票:0回答:1

Python doc 解释了重大更改:

3.8 版本中的新增功能:以前版本的 CPython 将解析 DLL 使用当前进程的默认行为。这导致 不一致,例如有时只搜索 PATH 或当前路径 工作目录和操作系统函数,例如 AddDllDirectory,没有 效果。

我从来没有遇到过这样的问题,我很乐意提供一个具体的例子。 我以前从未听说过

AddDllDirectory
,我很高兴。我曾经有一个可靠的过程:dll目录与环境路径一致。这使我能够轻松测试路径中是否有必要的 dll,例如,通过 dlldiag。我能够轻松读取和修改环境路径。这适用于 Windows 上的任何可执行文件,并且我有强大的工具来处理任何 dll 问题。

现在,我有了这个

os.add_dll_directory()
。我没有看到任何方法来阅读它,也没有方便的 var 可以修改。我无法将其中的内容与我的 dll 的已验证位置进行比较。传闻,这个功能用到底
AddDllDirectory
,其family中并没有额外的方便功能。

我尝试了以下简单的解决方案:

import os
for p in os.environ[ 'path' ].split( ';' ):
    if os.path.isdir( p ):
        os.add_dll_directory( p )

这解决了无用的错误消息

导入错误:导入 foo 时 DLL 加载失败:找不到指定的模块

这意味着找不到依赖的dll(上帝保佑它会清楚地告诉我缺少一个dll以及是哪个)。

然而,现在我收到了一条全新的无用消息:

导入错误:导入 foo 时 DLL 加载失败:操作系统无法运行 %1

这显然意味着路径中有两个候选dll,并且它不知道该怎么做(或者加载了错误的dll或其他什么)。

这是一个新的蠕虫罐头。我通常在路径中同时拥有 dll 的发布版本和调试版本,并且从来没有出现过这样的问题。现在,我必须非常小心地将它们分开,并使用我正在运行的正确版本或调试来指定每个目录。如果在我的管道中,我有一个脚本将另一个脚本作为不同的进程执行,那么,运气不好,这些新的 dll 路径不再被继承,您需要以某种方式将它们传递下去。

我该如何方便地处理这个问题,而不会给用户带来这些目录规范的负担? 我如何保持这个跨平台?现在,我需要 Windows 的特殊代码。

Python 突然决定打破其良好的跨平台行为,并开始干预晦涩的 Windows 功能。 而且,

win32api.LoadLibrary()
的功能现在与
ctypes
加载dll的方式不一致。

如何将加载 dll 的行为恢复到 Python 3.8 之前的方式?

python
1个回答
0
投票

看来我对第二个错误的结论是错误的。这不是与调试与发布相关的问题(感谢上帝——只是一个表达,我是一个无神论者)。这可能是错误的 dll 版本,因为我以相反的顺序设置了目录。更正后的代码是:

import os

def add():
    print( 'Adding dll dirs from env path' )

    paths = os.environ[ 'path' ].split( ';' )
    paths.reverse()
    for p in paths:
        if not os.path.isdir( p ):
            continue

        print( "Adding a dll dir:", p )
        os.add_dll_directory( p )

我认为这解决了我的主要问题,尽管我仍然对整件事不满意。

© www.soinside.com 2019 - 2024. All rights reserved.