PyPI包内跨平台获取共享对象库路径的最优方案
解决Python包中跨平台加载独立C扩展模块的问题
下面提供几种智能、跨平台且版本无关的实现方式:
方法1:利用importlib.machinery查找模块路径
借助Python的模块查找机制,自动定位扩展模块的实际路径,无需硬编码平台相关后缀或版本号:
# myPythonPkg/__init__.py import importlib.machinery import ctypes # 查找扩展模块的规格信息 ext_spec = importlib.machinery.PathFinder.find_spec("myFastCfunctions") if ext_spec is None: raise ImportError("无法找到myFastCfunctions扩展模块") # 加载共享库 fast_lib = ctypes.cdll.LoadLibrary(ext_spec.origin)
方法2:通过pkgutil获取模块文件路径
使用标准库pkgutil的加载器获取扩展模块路径,兼容所有平台:
# myPythonPkg/__init__.py import pkgutil import ctypes loader = pkgutil.get_loader("myFastCfunctions") if loader is None: raise ImportError("未找到myFastCfunctions模块") fast_lib = ctypes.cdll.LoadLibrary(loader.get_filename())
方法3:调整setup.py,将扩展模块嵌入包内(推荐)
修改setup.py,把扩展模块归属到myPythonPkg包名下,让模块结构更规整,加载逻辑更简单:
# 修改后的setup.py from distutils.core import setup, Extension setup( name="myPythonPkg", # ... 其他配置参数 packages=["myPythonPkg"], ext_modules=[ Extension('myPythonPkg.myFastCfunctions', ['myFastCfunctions.c']) ] )
安装后扩展模块会位于myPythonPkg目录下,此时在__init__.py中可以这样加载:
# myPythonPkg/__init__.py import importlib.util import ctypes # 查找包内的扩展模块 spec = importlib.util.find_spec("myPythonPkg.myFastCfunctions") if not spec: raise ImportError("包内未找到myFastCfunctions扩展模块") fast_lib = ctypes.cdll.LoadLibrary(spec.origin)
这种方式将扩展模块与Python包绑定,避免模块散落在site-packages根目录,同时完全适配不同平台的文件后缀与Python版本。
内容的提问来源于stack exchange,提问作者Doron Behar
相关产品推荐
相关产品推荐

