Python GitHub Actions 的矩阵测试策略

1次阅读

用 strategy.matrix 配合 include 显式定义合法组合,控制 job 数量在 6 个以内,按 python 版本分组管理依赖文件,将耗时操作移出矩阵,避免笛卡尔积导致超时或并发限流。

Python GitHub Actions 的矩阵测试策略

矩阵测试在 gitHub Actions 中怎么写才不爆炸

直接说结论:用 strategy.matrix 配合 includeexclude 控制组合,别硬套 Python 版本+依赖版本的笛卡尔积——多数项目根本不需要全量交叉,反而会触发超时或并发限制。

常见错误是照抄官方示例,把 python-versiondependency-version 全扔进 matrix,结果跑出 12 个 job,其中 8 个因 pip install django==4.0 在 Python 3.12 下失败而卡死。

  • 只对真正需要验证的维度做矩阵:比如 python-version: [3.9, 3.11, 3.12] + test-env: [unit, integration],而不是叠加 numpy-versiontorch-version
  • include 显式定义合法组合,比用 exclude 屏蔽非法组合更可靠(github Actions 对 exclude 的匹配逻辑容易漏掉)
  • 矩阵 job 数量建议压到 6 个以内;超过 8 个大概率触发 GitHub 托管 runner 的并发限流(Resource not accessible by integration 错误)

Python 版本和依赖版本怎么配才不冲突

GitHub Actions 的 setup-python 动作本身不解决依赖兼容性,它只装 Python 解释器。真正的坑在 pip install 阶段——特别是当你用 requirements.txt 固定版本后,又试图在多个 Python 版本下复用同一份文件。

典型现象:pip install -r requirements.txt 在 Python 3.9 成功,3.12 报 ModuleNotFoundError: No module named 'distutils.util',因为 setuptools 某些旧版已移除 distutils 支持。

立即学习Python免费学习笔记(深入)”;

  • 按 Python 版本分组管理依赖:用 if: matrix.python-version == '3.12' 切换不同的 requirements-312.txt
  • 避免在矩阵中混用 pip install .pip install -e .:前者可能跳过 pyproject.toml 中的构建后端检查,后者在某些矩阵 job 中因缓存污染导致 ImportError
  • 如果项目用 poetry,别在每个 job 里都 poetry install——改用 poetry export -f requirements.txt --without-hashes 提前生成适配各版本的 requirements 文件

怎么让矩阵测试快起来,又不漏关键路径

矩阵不是越多越好,而是要覆盖「执行路径差异最大」的组合。比如异步代码在 Python 3.11+ 有 asyncio.TaskGroup,但 3.9 只能用 asyncio.gather;这种逻辑分支必须测,但 black==23.1black==24.2 在同一 Python 版本下通常没必要双测。

  • strategy.fail-fast: false 确保一个 job 失败不影响其他 job 运行(默认是 true,容易误判整体失败)
  • 把耗时操作(如构建 wheel、下载大模型)提到矩阵外的单独 job,用 needs + outputs 传 artifact,避免每个矩阵 job 重复执行
  • 对非核心环境(如仅文档构建、仅 lint)不用矩阵,单独写成普通 job,用 if: github.event_name == 'push' && github.head_ref == 'main' 控制触发条件

本地调试矩阵 job 为什么总和 CI 行为不一致

根本原因是 GitHub Actions 的 matrix 是运行时展开的,而本地用 act 或直接跑脚本时,环境变量、路径、甚至 shell 类型(linux runner 默认 bashmacoszsh)都不同。最常踩的坑是 PATH 里没包含 ~/.local/bin,导致 pipx install black 装的命令在后续 step 找不到。

  • 在每个 job 开头加 echo "PATH: $PATH"which python,对比本地和 CI 输出
  • 别依赖 source ~/.bashrc 加载环境——runner 启动的是 non-interactive shell,不会自动读取 rc 文件
  • run: python -c "import sys; print(sys.version)" 替代 python --version,避免被 alias 或 wrapper 干扰

矩阵配置里最易被忽略的是 job 名称的可读性:name: Python ${{ matrix.python-version }} / ${{ matrix.test-env }} 比默认的 python-3.12 更容易定位失败点。还有就是 timeout-minutes 必须设,否则默认 6 小时超时,但很多矩阵 job 其实 10 分钟就该出结果了。

text=ZqhQzanResources