如何在命令行(Python)中获取`setup.cfg`元数据

8

如果你有一个setup.py文件,你可以通过如下命令获取包的名称:

C:\some\dir>python setup.py --name

以下内容将在命令行中打印包的名称。

为了遵循最佳实践,我试图通过将所有之前静态内容都放在 setup.cfg 中来迁移离开 setup.py

但是我们的构建管道依赖于能够调用 python setup.py --name。我正在寻找一种重写管道的方法,以使我不需要创建一个 setup.py 文件。

当你有 setup.cfg 但没有 setup.py 文件时是否有获取包名称的方法?


https://setuptools.pypa.io/en/latest/setuptools.html#setup-cfg-only-projects 介绍了关于 setup-cfg-only 项目的一些内容,它模拟了一个虚拟的 setup.py 文件,只需运行 setuptools.setup()。显式创建一个调用无参 setup() 方法的 setup.py 文件实际上会读取 setup.cfg,并足以获取名称,但我仍然想知道是否有更好的方法。 - myoungberg
2
保持最小化的 setup.py 是一种有效的解决方案。否则,使用解析。 setuptools 使用标准库中的 ConfigParser 读取 setup.cfg,因此,如答案所述,这是一种有效的解决方案。很快,setuptools 将支持 PEP 621 标准,该标准使用 TOML 格式,并将向 Python 的标准库(Python 3.11)添加一个 TOML 解析器,因此可以轻松地从几乎任何构建后端(不仅仅是 _setuptools_)提取信息。 - sinoroc
如果想要更进一步,能够从任何 PEP 517 项目(即 pyproject.toml)获取元数据(名称等),则可以构建某种 PEP 517 “构建前端”,专门用于此目的,并且只关注 prepare_metadata_for_build_wheel() 部分的事情,也许 pep517 可以帮助实现。 - sinoroc
使用 python -c 'import setuptools; setuptools.setup()' --name 命令。 - sinoroc
3个回答

5

简而言之,使用setuptools配置API。 https://setuptools.pypa.io/en/latest/setuptools.html#configuration-api

在您的情况下,此行将给出软件包的名称:

python -c 'from setuptools.config import read_configuration as c; print(c("setup.cfg")["metadata"]["name"])'

编辑:

在setuptools v61.0.0(2022年3月24日),setuptools.config.read_configuration已被弃用。使用新的API,命令变为:

python -c 'from setuptools.config.setupcfg import read_configuration as c; print(c("setup.cfg")["metadata"]["name"])'

说明:

Setuptools公开了一个read_configuration()函数,用于解析配置的元数据和选项部分。在内部,setuptools使用configparser模块来解析配置文件setup.cfg。对于像“name”键这样的简单的str类型数据,可以使用configparser来读取数据。但是,setuptools还允许使用指令进行动态配置,这些指令不能直接由configparser解析。

以下是一个示例,展示了替换python setup.py --version的两种不同方法之间的区别:

$ tree .
.
├── my_package
│   └── __init__.py
├── pyproject.toml
└── setup.cfg

1 directory, 3 files

$ cat setup.cfg
[metadata]
name = my_package
version = attr:my_package.__version__

[options]
packages = find:

$ cat my_package/__init__.py 
__version__ = "1.0.0"

$ cat pyproject.toml

$ python -c 'from setuptools.config import read_configuration as c; print(c("setup.cfg")["metadata"]["version"])'
1.0.0

$ python -c 'from configparser import ConfigParser; c = ConfigParser(); c.read("setup.cfg"); print(c["metadata"]["version"])'
attr:my_package.__version__


2
注意:如果您使用 pyproject.toml(使用 setuptools.build_meta 后端),则不一定需要解析 setup.cfg 文件,项目名称和版本将在 TOML 中指定(PEP621)。然后,这种方法会失败,但更简单的 python -c 'from setuptools import setup; setup()' --namepython3 -c 'from setuptools import setup; setup()' --version 应该在任何情况下都能继续工作。 - wim

4

也许可以使用 Python 模块 ConfigParser

python -c "from configparser import ConfigParser; cf = ConfigParser(); cf.read('setup.cfg'); print(cf['metadata']['name'])"

3
如果需要的元数据是版本号,但你遇到了一个项目声明了 "version=attr: my_package.version",那么这会引起很大的问题。这就是如何做到的,现在我已经滚动到足够的位置了:https://dev59.com/_sPra4cB1Zd3GeqPoMYA#71276404 - N1ngu

4

针对任何PEP 517兼容项目(即pyproject.toml),使用build项目提供的帮助,可以获得任何元数据字段的“过度解决方案”:

#!/usr/bin/env python3

import argparse
import pathlib

import build.util

def _main():
    args_parser = argparse.ArgumentParser()
    args_parser.add_argument('path')
    args = args_parser.parse_args()
    path_name = getattr(args, 'path')
    path = pathlib.Path(path_name)
    #
    metadata = build.util.project_wheel_metadata(path)
    print(metadata)

if __name__ == '__main__':
    _main()

这实际上会调用构建后端(setuptoolspoetryflitpdm 或其他),因此可能需要几秒钟。

build.util API 的文档在此处(在“latest”上)进行了记录(链接),它是在“0.7.0 (16-09-2021)”中添加的,具体请查看此更改


但是,实际上,正如您已经提到的,我建议仅保留最小限度的 setup.py

#!/usr/bin/env python3

import setuptools
setuptools.setup()

为了让 python setup.py --name 继续工作

当然,正如其他人已经说过的,解析是可行且简单的解决方案。 setuptools 使用标准库中的ConfigParser 来读取 setup.cfg 文件,所以您也可以这样做。


另一种可能的解决方案(wim 提供):

python -c 'import setuptools; setuptools.setup()' --name

与我的解决方案 https://dev59.com/AnIOtIcB2Jgan1znEAuT#71693117 不同,这个解决方案将会在构建后端未实现可选的 prepare_metadata_for_build_wheel 钩子时仍然有效。太好了!遗憾的是 build.util 不会显示在项目 API 文档中。 - N1ngu
1
@N1ngu 它在这里(在“_latest_”上):https://pypa-build.readthedocs.io/en/latest/api.html#module-build.util,有点令人困惑...它是在“0.7.0(2021年9月16日)”中添加的,详见此更改:https://github.com/pypa/build/pull/340。 - sinoroc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接