Windows环境下Python 3.10加载基于Boost 1.75.0的C++单元测试模块失败问题求助
我现在遇到一个棘手的问题,在Python里管理我的C++项目单元测试时卡壳了。
项目背景
这是个大型项目,重度依赖Boost库,包含多个dll/so文件,功能都导出到Python端使用。由于项目规模大,没法直接复制代码,也很难从中提取最小复现示例。而且我很确定这应该是配置问题,而非代码本身的问题,不过还是会贴出关键部分的代码供参考。
问题描述
我有一套C++写的单元测试逻辑,已经导出到Python中使用。在Python 3.8和3.9版本下,不管Windows还是Linux都运行正常;Linux下的Python 3.10也没问题,但Windows下用Python 3.10时,导入单元测试模块就会报错:
<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文件的目录加了进去,还专门用工具检查过依赖链。
更奇怪的是,项目里其他功能模块都能正常导入并调用,唯独这个单元测试模块在Windows+Python3.10的组合下导入失败。
环境配置
C++侧
- 使用Boost 1.75.0库,Windows上用Visual Studio 2019编译,Linux上用gcc 9.4
- 仅用到
boost_python和boost_numpy这两个用于C++与Python交互的库 - 所有Boost dll都是从源码编译的,为了适配不同Python版本(3.8/3.9/3.10),我给每个版本都单独配置了Anaconda虚拟环境,还打了一些补丁来支持新版本Python的要求
Python侧
我用的是Anaconda默认环境,这里列一下不同系统、不同Python版本对应的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/Python3.10换不同的Numpy版本(比如1.24.1),但问题依旧。
我知道Python 3.9到3.10之间有ABI变化,但Linux下3.10能正常运行,所以应该不是这个原因导致的。
已尝试的解决措施
为了解决这个问题,我已经做了这些尝试:
- 确认pyd文件的所有依赖库都存在
- 检查
sys.path的内容,确保相关路径已正确添加 - 用相同版本的Numpy编译所有Python版本对应的Boost库
- 给Python环境配置多个Numpy版本进行测试
关键代码示例
这里贴出Python端添加路径和导入单元测试模块的代码:
pythonMajorVersion = sys.version_info.major pythonMinorVersion = sys.version_info.minor pythonVersionSubDir = "Python" + str(pythonMajorVersion) + "_" + str(pythonMinorVersion) # 添加二进制文件目录到路径 binaryDir = getBinDir() # 存放dll的目录 if not binaryDir in sys.path: sys.path.insert(1, binaryDir) if os.name == "nt": os.environ["PATH"] = os.environ["PATH"] + ";" + binaryDir # Python pyd文件存放在对应版本的子目录,比如"Python3_8"、"Python3_9"或"Python3_10" 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 # 生成完整模块名,比如'PyUnitTestTools_1_0_0_0_x64',1.0.0.0是版本号 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+Python3.10这个特定配置下,我没法正常加载这个单元测试模块?
备注:内容来源于stack exchange,提问作者ractiv

