使用pyproject.toml构建Python包时,如何正确注入版本元数据
解决PDM下pyproject.toml元数据注入包内的问题
你的核心问题是运行时无法读取pyproject.toml(因为它不会被打包进安装后的包),PDM提供了原生解决方案,完全符合你的要求,不需要依赖外部文件或旧配置文件:
方案1:仅注入版本(最常用场景)
这是PDM官方推荐的动态版本管理方式,同时自动生成包内可访问的版本文件:
修改pyproject.toml
添加dynamic字段和PDM版本配置,指定版本生成到你的包目录下:[project] name = "mypackage" description = "你的包功能描述" dynamic = ["version"] # 声明版本为动态生成 [tool.pdm] # 可选版本源:从git tag自动获取(推荐开源项目) version = { source = "git" } # 或者固定版本,生成到包内的_version.py # version = { source = "file", path = "mypackage/_version.py", value = "0.1.0" }在包的__init__.py中导入版本
在mypackage/__init__.py中添加:from ._version import __version__ as VERSION __version__ = VERSION # 兼容常规的__version__命名习惯
安装后,用户就能通过以下方式访问版本:
>>> import mypackage >>> print(mypackage.VERSION) 0.1.0
方案2:注入所有元数据(名称、描述等)
如果需要把pyproject.toml中的所有元数据都注入包内,可通过PDM构建钩子在构建阶段自动生成元数据文件:
修改pyproject.toml添加构建钩子
[project] name = "mypackage" version = "0.1.0" description = "你的包功能描述" # 直接固定元数据,无需dynamic字段 [tool.pdm.build] hooks = [{"hook": "generate_metadata"}] [tool.pdm.build.hook.generate_metadata] script = "scripts/generate_metadata.py"编写元数据生成脚本
创建scripts/generate_metadata.py文件:import tomllib from pathlib import Path # 读取pyproject.toml中的元数据 with open("pyproject.toml", "rb") as f: pyproject = tomllib.load(f) project_meta = pyproject["project"] # 生成元数据文件到包目录 package_dir = Path("mypackage") package_dir.mkdir(exist_ok=True) meta_content = f'''# 自动生成,请勿手动修改 NAME = "{project_meta["name"]}" VERSION = "{project_meta["version"]}" DESCRIPTION = "{project_meta["description"]}" ''' with open(package_dir / "_metadata.py", "w", encoding="utf-8") as f: f.write(meta_content)在__init__.py中导入元数据
在mypackage/__init__.py中添加:from ._metadata import NAME, VERSION, DESCRIPTION
用户安装后即可直接访问这些元数据:
>>> import mypackage >>> print(mypackage.NAME, mypackage.VERSION, mypackage.DESCRIPTION) mypackage 0.1.0 你的包功能描述
为什么之前的方案失败?
你之前尝试直接读取pyproject.toml的方式,在本地开发时可行是因为文件存在,但pyproject.toml默认不会被包含在打包后的安装包中,所以用户安装后运行时会找不到文件,导致报错。上面的方案都是在构建阶段就把元数据写入到包内的Python文件中,安装后这些文件会被正常包含,完全解决了这个问题。
内容的提问来源于stack exchange,提问作者Mike Williamson
相关产品推荐
相关产品推荐

