setup()配置的属性能否作为包属性调用?my_package.version调用失败求助
问题解答
你的预期是否错误?
你的预期部分合理:可以让my_package拥有version(或更规范的__version__)属性,但author这类元数据默认不会自动成为包的模块属性——setup.py中定义的author、version只是包的元数据信息,会被存储在包的.dist-info目录中,不会自动注入到my_package模块的命名空间里。
问题出在哪?
你在setup.py中读取VERSION文件来设置包的构建元数据,但这个版本值并没有被写入到src/my_package/__init__.py中。当用户导入my_package时,Python只会加载该模块目录下的__init__.py(如果存在的话),而你的__init__.py里没有定义version属性,所以会抛出AttributeError。
如何修改实现需求?
这里提供两种常用的方案,推荐第一种(符合Python包的规范惯例):
方案一:在__init__.py中定义版本,让setup.py读取该值(避免重复维护)
这种方式让版本的唯一来源是包的__init__.py,同时setup.py从这里读取版本,避免多个地方维护版本导致不一致。
- 修改
src/my_package/__init__.py,添加以下内容:
# 定义规范的版本属性(Python社区惯例用双下划线) __version__ = "0.0.1" # 如果一定要直接用my_package.version,可以再加一行 version = __version__ # 同样可以定义author属性 __author__ = "ABC" author = __author__
- 修改setup.py,从包的
__init__.py读取版本和作者,而不是从VERSION文件:
import os import sys from setuptools import setup # 添加src目录到Python路径,让setup.py能导入my_package模块 sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src")) from my_package import __version__, __author__ setup( author=__author__, version=__version__, # 其他原有配置... )
此时用户导入包后,既可以用my_package.__version__(规范用法),也可以用my_package.version访问版本值。
方案二:从VERSION文件同步版本到__init__.py(适合需要单独维护VERSION文件的场景)
如果你想保留根目录的VERSION文件作为版本的唯一来源,可以让__init__.py也读取这个文件:
- 修改
src/my_package/__init__.py:
import re import os # 构建VERSION文件的绝对路径,避免相对路径问题 version_file_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "VERSION") VERSION_RE = re.compile(r"""([0-9dev.]+)""") with open(version_file_path, "r") as fh: version_content = fh.read().strip() __version__ = VERSION_RE.search(version_content).group(1) version = __version__ __author__ = "ABC" author = __author__
- setup.py可以保持原有读取VERSION文件的逻辑不变。
注意:方案二需要处理路径问题,确保安装后也能正确读取VERSION文件(如果包是源码安装的话),如果是wheel安装,可能需要额外配置让VERSION文件被包含进包中,所以方案一更稳妥。
内容的提问来源于stack exchange,提问作者dinhuun
相关产品推荐
相关产品推荐

