我使用 Gitlab CI 脚本缓存了 Pip 包,所以这不是问题。
现在我也想赶一个Conda虚拟环境,因为它减少了设置环境的时间。
我缓存了一个虚拟环境。不幸的是,最后需要很长时间才能缓存所有 venv 文件。
我尝试仅缓存
$CI_PROJECT_DIR/myenv/lib/python3.6/site-packages
文件夹,它似乎减少了管道的运行时间。
我的问题是:我做得正确吗?
脚本如下:
gitlab-ci.yml
image: continuumio/miniconda3:latest
cache:
paths:
- .pip
- ls -l $CI_PROJECT_DIR/myvenv/lib/python3.6/site-packages
- $CI_PROJECT_DIR/myvenv/lib/python3.6/site-packages
before_script:
- chmod +x gitlab-ci.sh
- ./gitlab-ci.sh
stages:
- test
test:
stage: test
script:
- python eval.py
gitlab-ci.sh
#!/usr/bin/env bash
ENV_NAME=myenv
ENV_REQUIREMENTS=requirements.txt
if [ ! -d $ENV_NAME ]; then
echo "Environment $ENV_NAME does not exist. Creating it now!"
conda create --path --prefix "$CI_PROJECT_DIR/$ENV_NAME"
fi
echo "Activating environment: $CI_PROJECT_DIR/$ENV_NAME"
source activate "$CI_PROJECT_DIR/$ENV_NAME"
echo "Installing PIP"
conda install -y pip
echo "PIP: installing required packages"
echo `which pip`
pip --cache-dir=.pip install -r "$ENV_REQUIREMENTS"
在构建之间重用 pip 缓存是一个非常好的主意,但对 virtualenvs 执行相同的操作是一个非常糟糕的主意。
这是因为 virtualenv 很容易变得混乱,而你在运行时无法真正检测到。这种情况不仅会发生,而且发生的频率比您想象的要高,因此请避免这种情况。
PS。来自经历过惨痛教训的人的建议。
我没有足够的代表来评论 @sorin 的答案,但我们现在在当前的 GitLab (14.6) 上遇到了同样的问题。
我们有四个作业,都使用相同的基础 Docker 镜像。其一,我们设置一个 virtualenv,然后缓存它;其他 3 个作业拉取缓存,激活 venv,然后尝试使用它。这 3 个作业经常失败,因为它们无法找到正确的 python 或从激活的 venv 加载特定模块。
virtualenv
的问题是(至少从Python 3.3中的venv模块开始)virtualenvs是不可重定位的。 activate
脚本在 VIRTUAL_ENV
变量中包含 virtualenv 的绝对路径。默认情况下,GitLab 运行程序将唯一的运行程序令牌作为 build 目录的一部分包含在内,然后该目录将成为该 VIRTUAL_ENV
变量的一部分。因此,如果您在一个运行器上缓存 virtualenv,然后尝试在另一个运行器上使用它,则会失败,因为路径不匹配。 activate
甚至不会警告您 VIRTUAL_ENV
路径不存在。
如果您有一个 GitLab 运行程序,那么您可能没问题。如果没有,您可以自己编写脚本来更新 virtualenv,这可能会或可能不会很好地工作(请参阅我可以移动 virtualenv 吗?)。或者做安全的事情,在每项工作中重新创造 venv;至少你可以不用缓存pip缓存。
我们成功使用了文档中概述的方法https://docs.gitlab.com/ee/ci/caching/#caching-python-dependency
# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
# Pip's cache doesn't store the python packages
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
#
# If you want to also cache the installed packages, you have to install
# them in a virtualenv and cache it as well.
cache:
paths:
- .cache/pip
- venv/
可能还缺少其他东西,但你的第一遍可能会错过:
.../venv/
目录树的大小时,您可能需要 .../venv/bin
,因为这是找到正确的 python 版本所必需的;使用命令 activate
venv
ing
which -a python3
pip
缓存,如上所示。在我们使用 Kubernetes 运行器的项目中,我们使用以下方法:
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
cache:
paths:
- .cache/pip
- venv
.python-base:
image: "some-image-with-python3"
before_script:
- test -f venv/bin/python || python3 -m venv venv
- source venv/bin/activate
- pip install --upgrade pip
- pip install -r requirements.txt
some-python-job:
extends: .python-base
k8s 运行器上的工作目录始终相同,因此引用不存在的目录没有问题。通过验证是否可以解析到 python 的链接,仅当 python 版本更改或不存在 venv 时才会创建新的 venv。
不确定还有什么其他事情会搞砸(参见sorin的回答),但对我们来说,到目前为止,这非常有效。我们主要将它用于作为构建本身的一部分运行的 python 脚本,这确实节省了时间。也许在使用它来生成其他地方使用的 python 包时更加谨慎是明智的。