
# GitHub Actions pip 缓存总失效?我踩过最深的 4 个坑
GitHub Actions 的 pip 缓存用不对,每次 CI 都重新下载几千个包,多花 1-3 分钟。本文记录我实际踩过的 4 个缓存失效场景,给出可直接复制的配置代码。
坑 1:hash 值作为 key,每次依赖变化都失效
错误配置
- name: Cache pip packages
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ hashFiles('**/requirements.txt') }}
问题分析
actions/cache@v4 在某些 Runner 版本下,key 的 hash 算法不稳定,每次生成的 key 都不一样,缓存永远命中不了。
另一个问题:Python 版本更新(3.11 → 3.12),即使 requirements.txt 没变,pip 包编译版本也不兼容,但缓存 key 里没有 Python 版本信息。
正确配置
- name: Cache pip packages
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ runner.os }}-${{ hashFiles('**/requirements.txt') }}-${{ hashFiles('.github/workflows/ci.yml') }}
restore-keys: |
pip-${{ runner.os }}-${{ hashFiles('**/requirements.txt') }}-
pip-${{ runner.os }}-
restore-keys 是关键:精确 key 匹配不到时,模糊匹配会尝试 fallback,最大化缓存利用率。
坑 2:用了 setup-python 但没指定固定版本
错误配置
- uses: actions/setup-python@v5
with:
python-version: '3.x' # ❌ 动态版本,每次可能不同
问题分析
python-version: '3.x' 会自动解析到最新的 3.x 版本。Runner 镜像更新后,可能从 3.11 变成 3.12,pip 包编译缓存就不通用了。
正确配置(推荐)
- uses: actions/setup-python@v5
with:
python-version: '3.11' # ✅ 固定版本
cache: 'pip' # ✅ setup-python 内置缓存
setup-python@v5 自带 pip 缓存支持,配置最简洁。
坑 3:多 Python 版本矩阵构建,缓存 key 没有隔离
错误场景
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip' # ✅ setup-python 已自动按版本隔离
问题分析
以为"3.10 的缓存 3.11 也能用"——错。pip 包有平台差异,不同 Python 版本的包也不完全兼容,必须独立缓存。
实际上用 setup-python 的 cache: 'pip' 已经自动按 Python 版本隔离了,但如果用 actions/cache 手动管理,就需要把 python-version 加入 key。
正确配置
- name: Cache pip packages
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }}
坑 4:requirements.txt 里的 git 引用或相对路径让 hash 不稳定
不稳定写法
requirements.txt:
-e git+https://github.com/user/repo.git@main#egg=pkg
-r ./local_requirements.txt
./some_package/
问题分析
git+https引用@main,每次 clone 的 commit hash 可能不同- 相对路径在不同 CI 环境下的路径解析可能不一致
- 本地包
./some_package/的 hash 会随包内容变化
解决方案
- name: Generate stable lock hash
run: |
cat requirements.txt | grep -v "^\\-e" | grep -v "^\\-r" | grep -v "^\\./" > requirements-stable.txt
echo "HASH=$(md5sum requirements-stable.txt | cut -d' ' -f1)" >> $GITHUB_OUTPUT
- name: Cache pip packages
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ runner.os }}-${{ hashFiles('requirements-stable.txt') }}
只对稳定依赖做 hash,排除 git 引用和相对路径。
完整正确配置示例
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements.txt'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest tests/
cache-dependency-path 显式指定用 requirements.txt 的 hash 做缓存 key,比默认行为更可控。
验证缓存是否生效
在 Action 日志里搜 cache-hit:
Cache hit: false— 缓存未命中Cache hit: true— 缓存命中
如果 cache-hit: false,先检查:requirements.txt 是否有变化、Python 版本是否改变、Runner OS 是否改变。
总结
| 坑 | 原因 | 修复方案 |
|---|---|---|
| hash 不稳定 | 动态版本或 git 引用 | 固定 Python 版本,过滤不稳定依赖 |
| key 缺少 OS | 不同 OS 的包不通用 | key 里加 runner.os |
| 用了 actions/cache 而非 setup-python | 配置复杂容易出错 | 优先用 setup-python 内置缓存 |
| 多版本缓存未隔离 | 每个版本需要独立 key | key 里加 python-version |
核心原则:缓存 key 必须包含所有影响依赖解析的变量(OS + Python 版本 + 稳定的依赖文件 hash),缺任何一个都会导致缓存失效。
更多交流点击入群






