Skip to main content

构建和测试 Python

了解如何创建持续集成 (CI) 工作流来构建和测试 Python 项目。

注意

GitHub Enterprise Server 目前不支持 GitHub 托管的运行器。

简介

本指南介绍如何构建、测试和发布 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. 在仓库名称下,单击“ Actions”****。

    “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@v5 - 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@v5 - 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@v5 - 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@v5 - 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@v5 - 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@v5 - 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@v5 - 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@v5 - 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@v5 - 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@v5 - 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@v5 - 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