无法在 Windows 上使用 python 3.10 加载 C++ 单元测试模块(使用 boost 1.75.0)

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

我在管理 Python 中的 C++ 项目的单元测试时遇到了一个具有挑战性的棘手问题。

项目

项目很大,强烈依赖boost,有几个dll/so文件,功能导出到python。所以我无法复制代码,也很难从所有这些代码中提取最小的样本。此外,我很确定这更多的是配置问题而不是代码问题。不过,我将提供一个关于关键部分的代码示例。

问题

我有一个 C++ 单元测试例程,可以在 python 中使用。它适用于 python 3.8 和 3.9。它也适用于 Linux 上的 python 3.10,但我在 Windows 上收到以下消息:

<class 'ImportError'> : DLL load failed while importing UnitTestTools_4_1_0_0_beta_x64: The specified module was not found.

我检查了依赖项,它们都存在,并且它们的位置都列在 sys.path 中。我使用

sys.path.insert(0, dirPath)
添加包含 dll/so 和 pyd 文件的目录。我还检查了 DependencyGui.exe

此外,我可以使用我的项目的所有功能,即我可以导入其他文件并调用它们包含的函数。仅在 Windows 上使用 Python 3.10 进行单元测试无法导入相关模块。

配置

C++ 方面,我使用 boost 1.75.0 并在 Windows 上使用 Visual Studio 2019 和在 Linux 上使用 gcc 9.4 构建项目。 我需要连接 C++ 和 python 的唯一库是 boost_python 和 boost_numpy。

我从源代码构建了 boost dll(使用一些补丁来管理最新的 python 要求),并为我需要支持的每个版本的 python(3.8、3.9 和 3.10)提供了专用的 Anaconda 虚拟环境。

Python 方面,当我在 python 中使用我的库时,我使用安装期间配置的默认 Anaconda 环境。我不会列出所有已安装的模块(如果需要,我可以提供更多),但这里是 python 和 numpy 版本的比较:

               | Windows | Linux
---------------+---------|-------
Python version |  3.9.13 | 3.9.7
Numpy version  |  1.24.1 | 1.26.3
---------------+---------|-------
Python version |  3.10.9 | 3.10.9
Numpy version  |  1.23.5 | 1.23.5

我还尝试了 Windows/Python 3.10 的几个版本的 numpy(例如 1.24.1)。

我发现 3.9 和 3.10 之间的 ABI 发生了变化,但我不认为这是我的问题的原因,因为它适用于 Linux。

解决尝试

作为我解决问题的所有尝试的总结,以下是我所做的:

  • 检查我的 pyd 的依赖项是否存在
  • 检查sys.path的内容
  • 为所有 python 版本构建具有相同 numpy 版本的 boost 1.75.0
  • 使用多个版本的numpy配置python环境

一些代码示例

为了以防万一它有帮助,我复制了有关单元测试模块导出的部分代码

pythonMajorVersion = sys.version_info.major
pythonMinorVersion = sys.version_info.minor
pythonVersionSubDir = "Python" + str(pythonMajorVersion) + "_" + str(pythonMinorVersion)

# add of binary directory to path
binaryDir = getBinDir() # Directory where the dlls are stored
if not binaryDir in sys.path:
    sys.path.insert(1, binaryDir)
if os.name == "nt":
    os.environ["PATH"] = os.environ["PATH"] + ";"  + binaryDir
# The python pyds are located in a specific subdirectory called "Python3_8",  "Python3_9" or  "Python3_10" depending on the python I'm using
pythonBinaryDir = os.path.join(binaryDir, pythonVersionSubDir)
if not pythonBinaryDir in sys.path:
    sys.path.insert(1, pythonBinaryDir)
if os.name == "nt":
    os.environ["PATH"] = os.environ["PATH"] + ";"  + pythonBinaryDir

 # Generate the full module name, for instance 'PyUnitTestTools_1_0_0_0_x64', 1.0.0.0 being the version number
unitTestModuleName = getLibName("PyUnitTestTools")

try:
    self.unittest = import_module(unitTestModuleName)
except:
    print("Failed to initialize unit test framework\n" + str(sys.exc_info()[0]) + " : " + str(sys.exc_info()[1]))

我不确定将库目录添加到

sys.path
os.environ["PATH"]
是否必要,但我尝试了以防万一它可以提供帮助。

我无法在此特定配置(Windows、Python 3.10)中加载单元测试模块吗?

python c++ python-3.x unit-testing boost
1个回答
0
投票

感谢 procmon (如 @Ahmed AEK 建议),我发现 python 3.9 在比 python 3.10 更多的目录中查找依赖项,即使两个 python 版本的 PATH 环境变量相同。

我的 .pyd 文件依赖于位于父目录中的 dll。该目录位于 PATH 变量环境中,但 python 3.10 忽略了它。

我在

dllDir = os.add_dll_directory(parent_path)
之前添加了
import_module(unitTestModuleName)
,现在 Python 3.10 找到了我的 dll。

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