Python3打包后使用importlib动态导入模块报ModuleNotFoundError问题
动态导入独立包内版本模块报错解决方案
错误根因
spec_from_file_location方法的第一个参数传入的模块名不符合全限定名规范,若模块内部存在相对导入逻辑,会无法找到父包上下文,触发模块找不到错误- 动态生成的模块未注册到全局
sys.modules字典中,路径解析时无法识别模块归属 - 原有代码直接将加载完成的模块对象赋值给
AdminApi变量,未取出模块内部定义的AdminApi类
修复后的实现代码
import importlib import os import sys from pathlib import Path # 按版本号生成唯一全限定模块名,避免全局命名冲突 module_full_name = f"admin_package.{version}.AdminApi" # 定位当前包根目录下对应版本的__init__.py文件 package_root = Path(__file__).resolve().parent target_module_path = os.path.join(package_root, version, "__init__.py") # 校验目标文件是否存在,可用于调试路径问题 if not os.path.exists(target_module_path): raise FileNotFoundError(f"版本{version}对应的模块文件不存在:{target_module_path}") # 生成模块加载规范 spec = importlib.util.spec_from_file_location(module_full_name, target_module_path) # 初始化模块对象 target_module = importlib.util.module_from_spec(spec) # 将模块注册到全局模块字典,解决上下文缺失问题 sys.modules[module_full_name] = target_module # 执行模块代码完成加载 spec.loader.exec_module(target_module) # 取出模块内定义的AdminApi类 AdminApi = target_module.AdminApi
*注:上述代码中admin_package需替换为你实际发布的独立包的根导入名称。
打包配置补充
需要在打包配置文件中声明将所有版本子目录纳入包数据,避免打包时遗漏对应文件:
pyproject.toml 配置示例
[tool.setuptools.package-data] "admin_package" = ["admin64/*", "admin65/*", "admin*/__init__.py"]
setup.py 配置示例
from setuptools import setup, find_packages setup( name="admin-package", version="1.0.0", packages=find_packages(), package_data={ "admin_package": ["admin64/*", "admin65/*", "admin*/__init__.py"] }, include_package_data=True )
内容的提问来源于stack exchange,提问作者S.D.
相关产品推荐
相关产品推荐

