简介
本指南将向您展示如何构建、测试和发布 Python 包。
GitHub 托管运行器具有一个包含预安装软件的工具缓存,其中包括 Python 和 PyPy。您无需安装任何内容!有关最新软件的完整列表以及 Python 和 PyPy 的预安装版本,请参阅“使用 GitHub 托管运行器”。
先决条件
您应该熟悉 YAML 和 GitHub Actions 的语法。有关更多信息,请参阅“编写工作流”。
我们建议您对 Python 和 pip 有基本了解。有关更多信息,请参阅
使用 Python 工作流模板
要快速入门,请将工作流模板添加到存储库的 .github/workflows
目录中。
如果您的存储库中至少包含一个 .py
文件,GitHub 提供了一个 Python 工作流模板,该模板应该可以正常工作。本指南后续部分提供了如何自定义此工作流模板的示例。
-
在 GitHub 上,导航到存储库的主页。
-
在您的存储库名称下,单击 操作.
-
如果您已经在存储库中拥有工作流,请单击新建工作流。
-
“选择工作流”页面显示了推荐的工作流模板选择。搜索“Python 应用程序”。
-
在“Python 应用程序”工作流上,单击配置。
-
根据需要编辑工作流。例如,更改 Python 版本。
-
单击提交更改。
python-app.yml
工作流文件将添加到存储库的.github/workflows
目录中。
指定 Python 版本
要在 GitHub 托管的运行器上使用预安装的 Python 或 PyPy 版本,请使用 setup-python
操作。此操作从每个运行器上的工具缓存中查找特定版本的 Python 或 PyPy,并将必要的二进制文件添加到 PATH
中,这些二进制文件将保留在作业的其余部分。如果工具缓存中没有预安装特定版本的 Python,则 setup-python
操作将从 python-versions
存储库下载并设置相应的版本。
使用 setup-python
操作是在 GitHub Actions 中使用 Python 的推荐方法,因为它确保了跨不同运行器和不同 Python 版本的一致行为。如果您使用的是自托管运行器,则必须安装 Python 并将其添加到 PATH
中。有关更多信息,请参阅 setup-python
操作。
下表描述了每个 GitHub 托管运行器中工具缓存的位置。
Ubuntu | Mac | Windows | |
---|---|---|---|
工具缓存目录 | /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 版本。有关更多信息,请参阅“在工作流中运行作业的变体”。
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)"
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 的最新次要版本。
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)"
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 的工作流语法”。
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"
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
时,PATH
中设置的 Python 默认版本将用于任何 shell。GitHub 托管运行器之间的 Python 默认版本有所不同,这可能会导致意外更改或使用比预期更旧的版本。
GitHub 托管运行器 | 描述 |
---|---|
Ubuntu | Ubuntu 运行器在 /usr/bin/python 和 /usr/bin/python3 下安装了多个版本的系统 Python。与 Ubuntu 捆绑在一起的 Python 版本除了 GitHub 安装在工具缓存中的版本之外。 |
Windows | 排除工具缓存中的 Python 版本,Windows 没有附带等效版本的系统 Python。为了保持与其他运行器的一致行为,并允许在不使用 setup-python 操作的情况下开箱即用地使用 Python,GitHub 将工具缓存中的几个版本添加到 PATH 中。 |
macOS | macOS 运行器安装了多个版本的系统 Python,除了工具缓存中包含的版本之外。系统 Python 版本位于 /usr/local/Cellar/python/* 目录中。 |
安装依赖项
GitHub 托管运行器已安装 pip 包管理器。您可以使用 pip 从 PyPI 包注册表安装依赖项,然后再构建和测试代码。例如,以下 YAML 安装或升级 pip
包安装程序以及 setuptools
和 wheel
包。
您还可以缓存依赖项以加快工作流速度。有关更多信息,请参阅“缓存依赖项以加快工作流速度”。
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
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。
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
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 的依赖项。
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
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
自述文件中的“缓存包依赖项”。
如果您有自定义需求或需要更精细的缓存控制,则可以使用 cache
操作。Pip 在不同的位置缓存依赖项,具体取决于运行器的操作系统。您需要缓存的路径可能与上面的 Ubuntu 示例不同,具体取决于您使用的操作系统。有关更多信息,请参阅 cache
操作存储库中的 Python 缓存示例。
测试您的代码
您可以使用与本地相同的命令来构建和测试代码。
使用 pytest 和 pytest-cov 进行测试
此示例安装或升级 pytest
和 pytest-cov
。然后运行测试并在 JUnit 格式中输出,同时代码覆盖率结果在 Cobertura 中输出。有关更多信息,请参阅 JUnit 和 Cobertura。
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
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 规范和/或格式化代码
以下示例安装或升级 ruff
并使用它来规范所有文件。有关更多信息,请参阅 Ruff。
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
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。
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
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
操作。
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@v4 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() }}
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@v4
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 令牌。
# This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. # GitHub recommends pinning actions to a commit SHA. # To get a newer version, you will need to update the SHA. # You can also reference a tag or branch, but the action may change without warning. 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@v4 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.ac.cn/p/YOURPROJECT steps: - name: Retrieve release distributions uses: actions/download-artifact@v4 with: name: release-dists path: dist/ - name: Publish release distributions to PyPI uses: pypa/gh-action-pypi-publish@6f7e8d9c0b1a2c3d4e5f6a7b8c9d0e1f2a3b4c5d
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
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@v4
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.ac.cn/p/YOURPROJECT
steps:
- name: Retrieve release distributions
uses: actions/download-artifact@v4
with:
name: release-dists
path: dist/
- name: Publish release distributions to PyPI
uses: pypa/gh-action-pypi-publish@6f7e8d9c0b1a2c3d4e5f6a7b8c9d0e1f2a3b4c5d
有关此工作流的更多信息,包括所需的 PyPI 设置,请参阅 在 PyPI 中配置 OpenID Connect。