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

How to get `setup.cfg` metadata at the command line (Python)

当你有一个setup.py文件时,你可以通过命令获取包名:

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

这会将包的名称打印到命令行。

为了坚持最佳实践,我试图通过将所有内容都放在 setup.cfg 中来从 setup.py 迁移,因为之前在 setup.py 中的所有内容都是静态内容.

但是我们的构建管道依赖于能够调用 python setup.py --name。我希望以不需要创建 setup.py 文件的方式重写管道。

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

也许使用 ConfigParser Python 模块?

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

对于允许从任何 PEP 517-compatible project (i.e. pyproject.toml), with the help of the build project 获取任何 meta-data 字段的“over-kill”解决方案:

#!/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()

这实际上会调用构建 back-end (setuptools, poetry, flitpdm 或 watever),所以这可能需要几秒钟。

build.util API 已记录 here (on "latest") and it was added in "0.7.0 (16-09-2021)", in this change


但是,是的,实际上,正如您已经说过的,我建议只保持最小值 setup.py:

#!/usr/bin/env python3

import setuptools
setuptools.setup()

以便python setup.py --name继续工作

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

TL;DR,使用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 was deprecated。使用新的 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。对于简单的str类型的数据,比如“name”键,可以使用configparser来读取数据。但是,setuptools 也允许 dynamic configuration using directives 不能直接用 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__