使用Poetry管理依赖,如何避免硬编码包名获取Python包版本?
解决方法
针对你的需求,这里提供几种靠谱的实现方式:
方案2:解析pyproject.toml提取包名
Python 3.11及以上版本自带tomllib库,可直接解析TOML文件;如果是3.11以下版本,需要先安装第三方库tomli(注意结尾是i),然后把代码里的tomllib替换成tomli。
具体代码
import tomllib # Python 3.11+;低版本用import tomli as tomllib import importlib.metadata import os def get_package_name(): # 从当前文件目录向上查找pyproject.toml,适配不同的脚本位置 current_dir = os.path.abspath(os.path.dirname(__file__)) while current_dir != os.path.dirname(current_dir): pyproject_path = os.path.join(current_dir, "pyproject.toml") if os.path.exists(pyproject_path): with open(pyproject_path, "rb") as f: config = tomllib.load(f) # Poetry管理的包名在tool.poetry.name字段下 return config["tool"]["poetry"]["name"] current_dir = os.path.dirname(current_dir) raise FileNotFoundError("项目根目录未找到pyproject.toml文件") # 获取并打印版本 pkg_name = get_package_name() version = importlib.metadata.version(pkg_name) print(f"当前包版本:{version}")
更稳妥的替代方案:在包内定义包名
如果不想做配置文件解析,还有个更简单可靠的方法——在你的包的__init__.py里直接定义包名:
# 比如你的包是mypackage,就在mypackage/__init__.py里加: __package_name__ = "mypackage"
之后在需要获取版本的地方直接引用:
import importlib.metadata from mypackage import __package_name__ version = importlib.metadata.version(__package_name__)
这种方式不用处理文件路径问题,也不会出现解析错误,是Python包的常规做法。
补充:为什么方案1不可靠
用__name__.split(".")[0]的问题在于:如果代码是直接执行的脚本(比如python my_script.py),__name__的值会是__main__,拆分后完全不对;另外如果包有多层嵌套结构,这种提取方式也可能拿到错误的顶层包名,所以确实不推荐。
内容的提问来源于stack exchange,提问作者sixtyfootersdude
相关产品推荐
相关产品推荐

