如何打包带有普通DLL依赖项的Python项目
普通C DLL依赖的Python包打包方案
下面分两种场景提供可直接落地的实现方式:
场景1:预编译好所有架构的DLL,直接打包分发
这种适合你已经提前在本地编译好Win32、x64等各架构的DLL,不需要用户端编译的情况:
- 先在项目根目录新增
MANIFEST.in文件,声明要打包的非Python文件,内容如下:include bin/Win32/Release/MyDLL.dll include bin/x64/Release/MyDLL.dll - 调整
setup.cfg配置,开启外部文件打包:[options] include_package_data = True packages = find: package_dir = = python - 在你的Python
package的__init__.py开头加入DLL路径注册逻辑,解决Windows下DLL搜索不到的问题:import os import platform import sys # 定位打包后的DLL根目录 current_path = os.path.dirname(os.path.abspath(__file__)) # 此处路径层级根据你打包后文件的安装位置调整,示例是从package目录向上两层到项目根目录 root_path = os.path.dirname(os.path.dirname(current_path)) # 匹配当前系统架构选对应DLL路径 arch = "Win32" if platform.architecture()[0] == "32bit" else "x64" dll_dir = os.path.join(root_path, "bin", arch, "Release") # 加入系统搜索路径 if dll_dir not in sys.path: sys.path.append(dll_dir) # 适配Windows 8及以上版本的DLL安全搜索规则 if hasattr(os, "add_dll_directory"): os.add_dll_directory(dll_dir) - 之后正常执行打包命令
python -m build即可,生成的wheel和sdist包都会自动包含对应DLL文件。如果需要分发不同架构的独立wheel包,可以在打包时指定--plat-name=win32或者--plat-name=win_amd64,并且打包时只保留对应架构的DLL,减少包体积。
场景2:用户安装时自动编译C源码生成DLL
如果需要支持用户端编译源码,不需要你预编译DLL,可以自定义setuptools的构建流程:
- 新增自定义构建类,继承
setuptools.Command或者setuptools.build_ext.build_ext,在构建阶段调用cmake、msbuild等工具编译cpp目录下的源码,生成的DLL输出到对应bin目录 - 把自定义构建类加入
setup.py的cmdclass参数,后续打包、安装时都会自动先执行C代码的编译逻辑,再完成Python包的打包/安装。
注意事项
- 加载DLL时直接用
ctypes.CDLL("MyDLL.dll")即可,不需要写绝对路径,提前注册的搜索路径会自动寻址 - 如果你的包需要支持跨平台,只需要对应扩展路径逻辑,匹配Linux的.so、Mac的.dylib文件路径即可
内容的提问来源于stack exchange,提问作者demberto
相关产品推荐
相关产品推荐

