软件包库中的 PyPI 包

在项目的软件包库中发布 PyPI 包。然后在需要将它们用作依赖项时安装它们。

软件包库适用于:

构建一个 PyPI 包

本节介绍如何创建 PyPI 包。

如果您已经使用 PyPI 并且知道如何构建自己的包,请转到 下一部分

安装 pip 和 twine

安装最新版本的 piptwine

创建项目

创建一个测试项目。

  1. 打开您的终端。
  2. 创建一个名为 MyPyPiPackage 的目录,然后进入该目录:

    mkdir MyPyPiPackage && cd MyPyPiPackage
    
  3. 创建另一个目录并转到它:

    mkdir mypypipackage && cd mypypipackage
    
  4. 在此目录中创建所需的文件:

    touch __init__.py
    touch greet.py
    
  5. 打开 greet.py 文件,然后添加:

    def SayHello():
        print("Hello from MyPyPiPackage")
        return
    
  6. 打开 __init__.py 文件,然后添加:

    from .greet import SayHello
    
  7. 要测试代码,请在您的 MyPyPiPackage 目录中启动 Python 提示符。

    python
    
  8. 运行此命令:

    >>> from mypypipackage import SayHello
    >>> SayHello()
    

一条消息表明项目已成功设置:

Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from mypypipackage import SayHello
>>> SayHello()
Hello from MyPyPiPackage

创建一个包

创建项目后,您可以创建包。

  1. 在您的终端中,转到 MyPyPiPackage 目录。
  2. 创建一个 setup.py 文件:

    touch setup.py
    

    该文件包含有关包的所有信息。有关此文件的更多信息,请参阅 创建 setup.py。由于极狐GitLab 根据 Python 规范化名称 (PEP-503) 识别包,请确保您的包名称满足这些要求。有关详细信息,请参阅安装部分

  3. 打开 setup.py 文件,然后添加基本信息:

    import setuptools
    
    setuptools.setup(
        name="mypypipackage",
        version="0.0.1",
        author="Example Author",
        author_email="author@example.com",
        description="A small example package",
        packages=setuptools.find_packages(),
        classifiers=[
            "Programming Language :: Python :: 3",
            "License :: OSI Approved :: MIT License",
            "Operating System :: OS Independent",
        ],
        python_requires='>=3.6',
    )
    
  4. 保存文件。
  5. 执行设置:

    python3 setup.py sdist bdist_wheel
    

输出应该在新创建的 dist 文件夹中可见:

ls dist

输出应类似于以下内容:

mypypipackage-0.0.1-py3-none-any.whl mypypipackage-0.0.1.tar.gz

该包现在已准备好发布到软件包库。

使用软件包库进行身份验证

在发布到软件包库之前,您必须进行身份验证。

为此,您可以使用:

  • 一个个人访问令牌,范围设置为api
  • 一个部署令牌,其范围设置为 read_package_registrywrite_package_registry 或两者都有。
  • CI 作业令牌

使用个人访问令牌进行身份验证

要使用个人访问令牌进行身份验证,请编辑 ~/.pypirc 文件并添加:

[distutils]
index-servers =
    gitlab

[gitlab]
repository = https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi
username = <your_personal_access_token_name>
password = <your_personal_access_token>

<project_id> 是项目的 URL-encoded 路径(例如,group%2Fproject),或者 项目的 ID(例如 42)。

使用部署令牌进行身份验证

要使用部署令牌进行身份验证,请编辑您的 ~/.pypirc 文件并添加:

[distutils]
index-servers =
    gitlab

[gitlab]
repository = https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi
username = <deploy token username>
password = <deploy token>

<project_id> 是项目的 URL-encoded路径(例如 group%2Fproject)或项目的 ID(例如 42)。

使用 CI 作业令牌进行身份验证

引入于 13.4 版本。

要在 GitLab CI/CD 中使用 PyPI 命令,您可以使用 CI_JOB_TOKEN 代替个人访问令牌或部署令牌。

例如:

image: python:latest

run:
  script:
    - pip install twine
    - python setup.py sdist bdist_wheel
    - TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*

您还可以在检入 GitLab 的 ~/.pypirc 文件中使用 CI_JOB_TOKEN

[distutils]
index-servers =
    gitlab

[gitlab]
repository = https://gitlab.example.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/pypi
username = gitlab-ci-token
password = ${env.CI_JOB_TOKEN}

验证访问群组内的包

按照上述令牌类型的说明进行操作,但使用组 URL 代替项目 URL:

https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi

发布 PyPI 包

先决条件:

然后,您可以使用 twine 发布包

确保您的版本字符串有效

如果您的版本字符串(例如,0.0.1)无效,则会被拒绝。 极狐GitLab 使用以下正则表达式来验证版本字符串。

\A(?:
    v?
    (?:([0-9]+)!)?                                                 (?# epoch)
    ([0-9]+(?:\.[0-9]+)*)                                          (?# release segment)
    ([-_\.]?((a|b|c|rc|alpha|beta|pre|preview))[-_\.]?([0-9]+)?)?  (?# pre-release)
    ((?:-([0-9]+))|(?:[-_\.]?(post|rev|r)[-_\.]?([0-9]+)?))?       (?# post release)
    ([-_\.]?(dev)[-_\.]?([0-9]+)?)?                                (?# dev release)
    (?:\+([a-z0-9]+(?:[-_\.][a-z0-9]+)*))?                         (?# local version)
)\z}xi

您可以使用此正则表达式编辑器来试验正则表达式并尝试您的版本字符串。

有关正则表达式的更多详细信息,请查看此文档

使用 twine 发布 PyPI 包

要发布 PyPI 包,请运行如下命令:

python3 -m twine upload --repository gitlab dist/*

此消息表明包已成功发布:

Uploading distributions to https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi
Uploading mypypipackage-0.0.1-py3-none-any.whl
100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.58k/4.58k [00:00<00:00, 10.9kB/s]
Uploading mypypipackage-0.0.1.tar.gz
100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.24k/4.24k [00:00<00:00, 11.0kB/s]

要查看已发布的包,请转到您项目的 软件包与镜像库 页面。

如果您没有使用 .pypirc 文件来定义仓库源,则可以使用内联身份验证发布到仓库:

TWINE_PASSWORD=<personal_access_token or deploy_token> TWINE_USERNAME=<username or deploy_token_username> python3 -m twine upload --repository-url https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi dist/*

如果您没有按照此页面上的步骤进行操作,请确保您的包已正确构建,并且您使用 setuptools 创建了一个 PyPI 包 .

然后,您可以使用以下命令上传您的包:

python -m twine upload --repository <source_name> dist/<package_file>

发布具有相同名称或版本的包

如果已存在具有相同名称和版本的包,则无法发布包。 您必须先删除现有的包。如果您尝试多次发布同一个包,则会发生 400 Bad Request 错误。

安装 PyPI 包

在 14.2 及更高版本中,当软件包库中未找到 PyPI 包时,将请求转发到 pypi.org

管理员可以在持续集成设置中禁用。

从项目级别安装

要安装最新版本的软件包,请使用以下命令:

pip install --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/projects/<project_id>/packages/pypi/simple --no-deps <package_name>
  • <package_name> 是包名。
  • <personal_access_token_name> 是具有 read_api 范围的个人访问令牌名称。
  • <personal_access_token> 是具有 read_api 范围的个人访问令牌。
  • <project_id> 是项目的 URL-encoded 路径(例如,group%2Fproject),或者项目的 ID(例如 42)。

在这些命令中,您可以使用 --extra-index-url 代替 --index-url。 但是,使用--extra-index-url 会使您容易受到依赖混淆攻击,因为它会在检查自定义仓库之前检查 PyPi 仓库中的包。--extra-index-url 将提供的 URL 添加为额外的库,客户端检查包是否存在。--index-url 告诉客户端只在提供的 URL 上检查包。

如果您遵循指南并想要安装 MyPyPiPackage 包,您可以运行:

pip install mypypipackage --no-deps --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/simple

此消息表明软件包已成功安装:

Looking in indexes: https://<personal_access_token_name>:****@gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/simple
Collecting mypypipackage
  Downloading https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/pypi/files/d53334205552a355fee8ca35a164512ef7334f33d309e60240d57073ee4386e6/mypypipackage-0.0.1-py3-none-any.whl (1.6 kB)
Installing collected packages: mypypipackage
Successfully installed mypypipackage-0.0.1

从群组级别安装

要从群组安装最新版本的软件包,请使用以下命令:

pip install --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/groups/<group_id>/-/packages/pypi/simple --no-deps <package_name>

在此命令中

  • <package_name> 是包名称。
  • <personal_access_token_name> 是具有 read_api 范围的个人访问令牌名称。
  • <personal_access_token> 是具有 read_api 范围的个人访问令牌。
  • <group_id> 是群组 ID。

在这些命令中,您可以使用 --extra-index-url 代替 --index-url。 但是,使用 --extra-index-url 会使您容易受到依赖混淆攻击,因为它会在检查自定义仓库之前检查 PyPi 仓库中的包。 --extra-index-url 将提供的 URL 添加为额外的库,客户端检查包是否存在。--index-url 告诉客户端只在提供的 URL 上检查包。

如果您按照指南并想要安装 MyPyPiPackage 包,您可以运行:

pip install mypypipackage --no-deps --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/pypi/simple

包名称

极狐GitLab 查找使用 Python 规范化名称 (PEP-503) 的包。 字符 -_. 都被同等对待,并删除重复的字符。

my.packagepip install 请求会查找与三个字符中的任何一个匹配的包,例如 my-packagemy_packagemy....package

故障排查

为了提高性能,PyPI 缓存与包相关的文件。请注意,PyPI 不会自行删除数据。缓存随着新软件包的安装而增长。如果遇到问题,请使用以下命令清除缓存:

pip cache purge

支持的 CLI 命令

GitLab PyPI 仓库支持以下 CLI 命令:

  • twine upload:将包上传到软件包库。
  • pip install:从软件包库安装 PyPI 包。