Python3包setup.py导入__about__.py时依赖未装引发导入错误的解决
这是一个非常典型的Python包开发痛点——在安装阶段导入包内元数据时触发了依赖未就绪的导入错误。既然你想保留现有结构和用户使用方式,最优解确实是不通过常规import读取__about__.py,而是直接解析文件内容获取元数据,下面是具体实现和备选方案:
最优方案:通过AST解析
__about__.py(不执行任何包代码) 这个方法的核心是用Python的ast模块安全解析__about__.py的代码结构,提取元数据变量(比如__version__、__author__),全程不会触发包的__init__.py执行,从根本上避免依赖未安装的问题。
在你的setup.py中替换原有的导入逻辑,改成以下代码:
import ast import os def get_package_metadata(): # 定位__about__.py的路径 about_file_path = os.path.join( os.path.dirname(__file__), "mypackage", "__about__.py" ) # 读取文件内容 with open(about_file_path, "r", encoding="utf-8") as f: about_content = f.read() # 解析AST语法树,不执行代码 ast_tree = ast.parse(about_content) metadata = {} # 遍历语法树,提取以__开头和结尾的元数据变量 for node in ast.walk(ast_tree): if isinstance(node, ast.Assign): for target in node.targets: if isinstance(target, ast.Name) and target.id.startswith("__") and target.id.endswith("__"): try: # 安全计算字面量值(仅支持字符串、数字等简单类型,元数据通常都是这类) metadata[target.id] = ast.literal_eval(node.value) except (ValueError, TypeError): # 如果是复杂表达式(比如函数调用),可以跳过或根据需求处理 pass return metadata # 获取元数据 package_metadata = get_package_metadata() # 后续setup函数直接使用这些元数据 from setuptools import setup setup( name="mypackage", version=package_metadata["__version__"], author=package_metadata["__author__"], # 其他setup参数... install_requires=[ # 你的第三方依赖列表 "requests>=2.25.0", "numpy>=1.21.0" ] )
这个方案的优势:
- 完全不触发包的初始化流程,
__init__.py和深层代码都不会执行 - 保留了你原有的包结构和用户使用习惯(用户依然可以
import mypackage后直接用mypackage.MyClass) - 安全可靠,不会因为依赖缺失抛出异常
备选方案:修改
__init__.py,避免安装阶段导入依赖模块 如果不想修改setup.py的元数据读取逻辑,可以在__init__.py中添加判断,仅在非安装阶段才导入依赖的模块:
import sys def is_installation_running(): # 检查调用栈是否包含setup.py或pip相关进程 for frame in sys._current_frames().values(): current_frame = frame while current_frame: filename = current_frame.f_code.co_filename if "setup.py" in filename or "pip" in filename: return True current_frame = current_frame.f_back return False # 仅在非安装阶段导入依赖模块 if not is_installation_running(): from mypackage.mymodule import MyClass
这个方案的缺点是依赖调用栈检测,某些特殊安装场景(比如自定义安装脚本)可能会误判,但胜在改动小,适合快速临时解决问题。
内容的提问来源于stack exchange,提问作者vlk
相关产品推荐
相关产品推荐

