如何找到对应于 PyPI 条目的现有 deb 包?

How to find existing deb package corresponding to PyPI entry?

PyPI 有很多包,其中许多确实有针对特定 Debian 发行版的 deb 等价物。它通常通过在原始包的名称前添加 python-python3- 来实现,可能还有一些其他更改,如小写等,但并非总是如此。

有什么好的方法自动建立PyPI->Debian版本X对应关系吗?

例如,给定一个 requirements.txt 文件(或 运行 pip freeze 的结果),是否有任何工具可以列出 Debian 软件包?

也许,有一些服务可以给定 "PyPI name",returns Debian 的搜索结果?我不太熟悉 Debian 工具,但也许有一个工具可以将其作为 Debian 使用的某些过程的一部分进行自动化?

例如:alembic package. Source package is a basis to create python-prefixed packages. And description points to where it was taken from. Then on PyPI there is a page 用于特定版本文件(可能还有某处的元数据描述)。

无法通过谷歌搜索找到它,因为搜索结果显示很多如何制作您自己的包,这是一个不同的主题。

到目前为止,该过程非常耗时且需要大量手动操作,使用 apt-file search -l 查询包含某些文件的包。

这里是 PyPI 管理员:据我所知,没有这样的工具。 Python 软件包经常被重新分发为 Debian 软件包,原始维护者几乎没有输入,并且在发生这种情况时无法保证奇偶校验。

我很好奇为什么您更喜欢使用重新分发的 Debian 软件包而不是原始的 Python 软件包。也许这是一个 XY Problem?

受此答案启发:https://askubuntu.com/a/1912

$ apt-file --package-only --regex search 'alembic\-.*\.egg\-info'
python-alembic
python3-alembic
$ apt-file --package-only --regex search 'setuptools\-.*\.egg\-info'
pypy-setuptools
python-setuptools
python3-setuptools

不确定正则表达式,很可能它可以改进很多。


短 Python 包装器脚本为例:

import argparse
import subprocess

import pkg_resources  # from 'setuptools'


def _main():
    parser = argparse.ArgumentParser(allow_abbrev=False)
    parser.add_argument(
        'requirements',
        metavar='requirements.txt',
        type=argparse.FileType('r'),
    )
    args = parser.parse_args()
    #
    requirements = [
        requirement.project_name
        for requirement
        in pkg_resources.parse_requirements(args.requirements)
    ]
    print(requirements)
    #
    regex = r'({})\-.*\.egg\-info'.format(
        '|'.join(
            [
                requirement.replace('-', '_')
                for requirement
                in requirements
            ],
        ),
    )
    #
    output = subprocess.check_output(
        [
            'apt-file',
            '--package-only',
            '--regex',
            'search',
            regex,
        ],
    )
    print(output.decode())


if __name__ == '__main__':
    _main()