Skip to main content

此版本的 GitHub Enterprise Server 已于以下日期停止服务 2024-09-25. 即使针对重大安全问题,也不会发布补丁。 为了获得更好的性能、更高的安全性和新功能,请升级到最新版本的 GitHub Enterprise。 如需升级帮助,请联系 GitHub Enterprise 支持

构建和测试 Python

您可以创建持续集成 (CI) 工作流程来构建和测试您的 Python 项目。

Note

GitHub Enterprise Server 目前不支持 GitHub 托管的运行器。 可以在 GitHub public roadmap 上查看有关未来支持计划的更多信息。

简介

本指南介绍如何构建、测试和发布 Python 包。

GitHub 托管的运行器具有预安装了软件的工具缓存,包括 Python 和 PyPy。 您无需安装任何项目! 有关最新软件和预安装版本的 Python 和 PyPy 的完整列表,请参阅“使用 GitHub 托管的运行器”。

先决条件

您应该熟悉 YAML 和 GitHub Actions 的语法。 有关详细信息,请参阅“写入工作流”。

建议你对 Python 和 pip 有基本的了解。 有关详细信息,请参阅:

在 GitHub Enterprise Server 上使用自托管的运行器

在包含自承载运行器的 GitHub Enterprise Server 上使用设置操作(例如 actions/setup-LANGUAGE)时,可能需要在无法访问 Internet 的运行器上设置工具缓存。 有关详细信息,请参阅“在未接入互联网的自托管运行器上设置工具缓存”。

使用 Python 工作流模板

若要快速开始使用,请将工作流模板添加到存储库的 .github/workflows 目录。

GitHub 为 Python 提供了一个工作流模板,如果存储库已包含至少一个 .py 文件,则该工作流应正常工作。 本指南的后续部分提供了如何自定义此工作流模板的示例。

  1. 在 GitHub 上,导航到存储库的主页面。

  2. 在存储库名称下,单击 “操作”。

    “github/docs”存储库的选项卡的屏幕截图。 “操作”选项卡以橙色边框突出显示。

  3. 如果存储库中已有工作流,请单击“新建工作流”。

  4. “选择工作流”页面显示一系列推荐的工作流模板。 搜索“Python application”。

  5. 在“Python 应用程序”工作流上,单击“配置”。

    如果未找到“Python 应用程序”工作流模板,请将以下工作流代码复制到存储库的 .github/workflows 目录中名为 python-app.yml 的新文件。

    YAML
    name: Python application
    
    on:
      push:
        branches: [ "main" ]
      pull_request:
        branches: [ "main" ]
    
    permissions:
      contents: read
    
    jobs:
      build:
        runs-on: ubuntu-latest
    
        steps:
        - uses: actions/checkout@v4
        - name: Set up Python 3.13
          uses: actions/setup-python@v5
          with:
            python-version: "3.13"
        - name: Install dependencies
          run: |
            python -m pip install --upgrade pip
            pip install ruff pytest
            if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
        - name: Lint and format Python code with ruff
          run: |
           # Lint with the default set of ruff rules with GitHub Annotations
           ruff check --format=github --target-version=py39
           # Verify the code is properly formatted
           ruff format --diff --target-version=py39
        - name: Test with pytest
          run: |
            pytest
    
  6. 根据需要编辑工作流。 例如更改 Python 版本。

  7. 单击“提交更改”。

指定 Python 版本

若要在 GitHub 托管的运行器上使用 Python 或 PyPy 的预安装版本,请使用 setup-python 操作。 此操作从每个运行器上的工具缓存中查找特定版本的 Python 或 PyPy,并将必要的二进制文件添加到 PATH,这可继续用于作业的其余部分。 如果工具缓存中未预装特定版本的 Python,则 setup-python 操作将从 python-versions 存储库下载并设置适当的版本。

使用 setup-python 是 Python 与 GitHub Actions 结合使用时的推荐方式,因为它能确保不同运行器和不同版本的 Python 行为一致。 如果使用自托管运行器,则必须安装 Python 并将其添加到 PATH。 有关详细信息,请参阅 setup-python 操作

下表描述了每个 GitHub 托管的运行器中工具缓存的位置。

UbuntuMacWindows
工具缓存目录/opt/hostedtoolcache/*/Users/runner/hostedtoolcache/*C:\hostedtoolcache\windows\*
Python 工具缓存/opt/hostedtoolcache/Python/*/Users/runner/hostedtoolcache/Python/*C:\hostedtoolcache\windows\Python\*
PyPy 工具缓存/opt/hostedtoolcache/PyPy/*/Users/runner/hostedtoolcache/PyPy/*C:\hostedtoolcache\windows\PyPy\*

如果使用的是自托管运行器,则可以将运行器配置为使用 setup-python 操作来管理依赖项。 有关详细信息,请参阅 setup-python 自述文件中的将 setup-python 与自托管运行器结合使用

GitHub 支持语义版本控制语法。 有关详细信息,请参阅“使用语义版本控制”和“语义版本控制规范”。

使用多个 Python 版本

以下示例使用作业的矩阵来设置多个 Python 版本。 有关详细信息,请参阅“在工作流中运行作业的变体”。

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["pypy3.10", "3.9", "3.10", "3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v4
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"

使用特定的 Python 版本

可以配置特定版本的 Python。 例如 3.12。 或者,您也可以使用语义版本语法来获得最新的次要版本。 此示例使用 Python 3 最新的次要版本。

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        # This is the version of the action for setting up Python, not the Python version.
        uses: actions/setup-python@v5
        with:
          # Semantic version range syntax or exact version of a Python version
          python-version: '3.x'
          # Optional - x64 or x86 architecture, defaults to x64
          architecture: 'x64'
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"

排除版本

如果指定的 Python 版本不可用,则 setup-python 将失败并出现错误,例如:##[error]Version 3.7 with arch x64 not found。 错误消息包含可用的版本。

如果存在不想运行的 Python 配置,也可以在工作流中使用 exclude 关键字。 有关详细信息,请参阅“GitHub Actions 的工作流语法”。

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.9", "3.11", "3.13", "pypy3.10"]
        exclude:
          - os: macos-latest
            python-version: "3.11"
          - os: windows-latest
            python-version: "3.11"

使用默认 Python 版本

建议使用 setup-python 来配置工作流中使用的 Python 版本,因为它有助于明确依赖项。 如果不使用 setup-python,当调用 python 时,将在任何 shell 中使用 PATH 中设置的默认 Python 版本。 GitHub 托管的运行器之间有不同的 Python 默认版本,这可能导致非预期的更改或使用的版本比预期更旧。

GitHub 托管的运行器说明
UbuntuUbuntu 运行器在 /usr/bin/python/usr/bin/python3 下安装了多个版本的系统 Python。 GitHub 除了安装在工具缓存中的版本,还有与 Ubuntu 一起打包的 Python 版本。
Windows不包括工具缓存中的 Python 版本,Windows 未随附同等版本的系统 Python。 为保持与其他运行器一致的行为,并允许 Python 在没有 setup-python 操作的情况下开箱即用,GitHub 将从工具缓存中添加几个版本到 PATH
macOS除了作为工具缓存一部分的版本外,macOS 运行器还安装了多个版本的系统 Python。 系统 Python 版本位于 /usr/local/Cellar/python/* 目录中。

安装依赖关系

GitHub 托管的运行器安装了 pip 软件包管理器。 在构建和测试代码之前,您可以使用 pip 从 PyPI 软件包注册表安装依赖项。 例如,下面的 YAML 安装或升级 pip 包安装程序以及 setuptoolswheel 包。

可以缓存依赖项来加快工作流运行。 有关详细信息,请参阅“缓存依赖项以加快工作流程”。

YAML
steps:
- uses: actions/checkout@v4
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: python -m pip install --upgrade pip setuptools wheel

要求文件

更新 pip 后,下一步通常是从 requirements.txt 安装依赖项。 有关详细信息,请参阅 pip

YAML
steps:
- uses: actions/checkout@v4
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt

缓存依赖项

可以使用 setup-python 操作缓存和还原依赖项。

以下示例缓存 pip 的依赖项。

YAML
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
    cache: 'pip'
- run: pip install -r requirements.txt
- run: pip test

默认情况下,setup-python 操作将在整个存储库中搜索依赖项文件(对于 pip,该文件为 requirements.txt;对于 pipenv,文件为 Pipfile.lock;对于 poetry,则为 poetry.lock)。 有关详细信息,请参阅 setup-python README 中的“缓存包依赖项”。

如果有自定义要求或需要更精细的缓存控制,可以使用 cache 操作。 Pip 根据运行器的操作系统将依赖项缓存在不同的位置。 您需要缓存的路径可能不同于上面的 Ubuntu 示例,具体取决于您使用的操作系统。 有关详细信息,请参阅 cache 操作存储库中的 Python 缓存示例

测试代码

您可以使用与本地相同的命令来构建和测试代码。

使用 pytest 和 pytest-cov 测试

此示例安装或升级 pytestpytest-cov。 然后进行测试并以 JUnit 格式输出,而代码覆盖结果则以 Cobertura 输出。 有关详细信息,请参阅 JUnitCobertura

YAML
steps:
- uses: actions/checkout@v4
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
- name: Test with pytest
  run: |
    pip install pytest pytest-cov
    pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html

使用 Ruff 对代码进行 Lint 分析和/或设置代码格式

以下示例安装或升级 ruff 并使用它对所有文件执行 lint 操作。 有关详细信息,请参阅 Ruff

YAML
steps:
- uses: actions/checkout@v4
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install the code linting and formatting tool Ruff
  run: pipx install ruff
- name: Lint code with Ruff
  run: ruff check --output-format=github --target-version=py39
- name: Check code formatting with Ruff
  run: ruff format --diff --target-version=py39
  continue-on-error: true

格式设置步骤已设置 continue-on-error: true。 这可防止在格式设置步骤不成功时工作流失败。 解决所有格式设置错误后,可以删除此选项,以便工作流捕获新问题。

使用 tox 运行测试

通过 GitHub Actions,您可以使用 tox 运行测试并将工作分散到多个作业。 需要使用 -e py 选项调用 tox,以选择 PATH 中的 Python 版本,而不是指定特定版本。 有关详细信息,请参阅 tox

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python: ["3.9", "3.11", "3.13"]

    steps:
      - uses: actions/checkout@v4
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python }}
      - name: Install tox and any other packages
        run: pip install tox
      - name: Run tox
        # Run tox using the version of Python in `PATH`
        run: tox -e py

将工作流数据打包为构件

您可以在工作流程完成后上传构件以查看。 例如,您可能需要保存日志文件、核心转储、测试结果或屏幕截图。 有关详细信息,请参阅“从工作流存储和共享数据”。

以下示例演示如何使用 upload-artifact 操作来存档运行 pytest 得到的测试结果。 有关详细信息,请参阅 upload-artifact 操作

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v4
      - name: Setup Python # Set Python version
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      # Install pip and pytest
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest
      - name: Test with pytest
        run: pytest tests.py --doctest-modules --junitxml=junit/test-results-${{ matrix.python-version }}.xml
      - name: Upload pytest test results
        uses: actions/upload-artifact@v3
        with:
          name: pytest-results-${{ matrix.python-version }}
          path: junit/test-results-${{ matrix.python-version }}.xml
        # Use always() to always run this step to publish test results when there are test failures
        if: ${{ always() }}

发布到 PyPI

可以配置工作流,以便在 CI 测试通过后将 Python 包发布到 PyPI。 本部分演示如何在每次发布版本时使用 GitHub Actions 将包上传到 PyPI。 有关详细信息,请参阅“管理仓库中的发行版”。

下面的示例工作流使用“受信任的发布”对 PyPI 进行身份验证,无需手动配置的 API 令牌。

YAML
# 此工作流使用未经 GitHub 认证的操作。
# 它们由第三方提供,并受
# 单独的服务条款、隐私政策和支持
# 文档。

# GitHub 建议将操作固定到提交 SHA。
# 若要获取较新版本,需要更新 SHA。
# 还可以引用标记或分支,但该操作可能会更改而不发出警告。

name: Upload Python Package

on:
  release:
    types: [published]

permissions:
  contents: read

jobs:
  release-build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.x"

      - name: Build release distributions
        run: |
          # NOTE: put your own distribution build steps here.
          python -m pip install build
          python -m build

      - name: Upload distributions
        uses: actions/upload-artifact@v3
        with:
          name: release-dists
          path: dist/

  pypi-publish:
    runs-on: ubuntu-latest

    needs:
      - release-build

    permissions:
      # IMPORTANT: this permission is mandatory for trusted publishing
      id-token: write

    # Dedicated environments with protections for publishing are strongly recommended.
    environment:
      name: pypi
      # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
      # url: https://pypi.org/p/YOURPROJECT

    steps:
      - name: Retrieve release distributions
        uses: actions/download-artifact@v3
        with:
          name: release-dists
          path: dist/

      - name: Publish release distributions to PyPI
        uses: pypa/gh-action-pypi-publish@6f7e8d9c0b1a2c3d4e5f6a7b8c9d0e1f2a3b4c5d