GitLabCI怎么执行python脚本流水线
详细讲解在GitLab CI中配置与执行Python脚本流水线的完整方法,涵盖目录结构准备、.gitlab-ci.yml编写、Docker与Shell执行器差异、pip依赖缓存、参数与环境变量传递、产物收集及常见报错排查。
假设团队在代码仓库中维护了一份用于校验数据格式并生成汇总报告的 Python 脚本 scripts/check_report.py,每次有人提交代码或合并分支时,如果靠人工在本地运行脚本,很容易因为忘记执行或本地第三方库版本不一致而遗漏错误。要在 GitLab CI 中自动执行 Python 脚本流水线,核心做法是在仓库根目录创建 .gitlab-ci.yml 文件,声明包含 Python 环境的运行镜像(或使用已安装 Python 的 Runner 主机),在 before_script 中安装依赖,并在 script 字段中编写调用 python scripts/check_report.py 的命令。本文将按实际配置顺序,完整说明从文件准备、编写流水线配置、传递变量与收集产物,到排查常见报错的具体方法。
一、GitLab CI 运行 Python 脚本的工作机制与环境准备
在开始编写配置前,需要先确认代码仓库具备可运行的 GitLab Runner,并且明确脚本在流水线中的执行位置。GitLab 本身负责管理代码与解析 .gitlab-ci.yml,真正执行 Python 命令的是关联到项目的 GitLab Runner。当代码推送到仓库后,GitLab 会根据配置文件生成流水线任务(Job),将任务分发给 Runner;Runner 拉取当前提交的代码,准备 Python 运行环境,按顺序执行配置好的终端命令,并根据命令的退出状态码(Exit Code)判断任务成功还是失败。
为了让后文的命令和路径前后一致,下面以一个包含数据检查脚本与单元测试的标准仓库结构为例。请在项目根目录下确认文件组织如下:
my-python-pipeline/
├── .gitlab-ci.yml
├── requirements.txt
├── scripts/
│ └── check_report.py
└── tests/
└── test_report.py
其中 requirements.txt 声明脚本依赖的第三方包及固定版本,避免每次流水线拉取到不兼容的新版本:
requests==2.31.0
pytest==8.1.1
scripts/check_report.py 是需要在流水线中运行的目标脚本。脚本通过读取环境变量或命令行参数执行检查,并将结果写入 output/summary.json 文件中。当检查不通过时,使用 sys.exit(1) 返回非零状态码,这样 GitLab CI 才能准确识别任务失败:
import json
import os
import sys
from pathlib import Path
def main():
env_name = os.getenv("TARGET_ENV", "staging")
threshold = int(os.getenv("MIN_SCORE", "80"))
current_score = 85
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)
report_data = {
"environment": env_name,
"threshold": threshold,
"actual_score": current_score,
"passed": current_score >= threshold
}
report_path = output_dir / "summary.json"
report_path.write_text(json.dumps(report_data, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"[INFO] 报告已生成: {report_path},当前环境: {env_name},得分: {current_score}")
if not report_data["passed"]:
print("[ERROR] 得分低于阈值,流水线校验未通过", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
sys.exit(1) 或重新抛出异常,进程默认以退出码 0 结束,流水线会误判为执行成功(显示绿色通过图标)。
二、配置并运行 Python 流水线的操作步骤
完成脚本和依赖文件准备后,即可通过编写 .gitlab-ci.yml 将 Python 脚本接入自动化流水线。整个配置与验证过程分为五个步骤。
步骤 1:确认项目的 GitLab Runner 状态
在 GitLab 网页端打开目标项目,依次进入左侧菜单的 Settings(设置) > CI/CD,展开 Runners 区域。确认页面中存在旁边带有绿色圆点的可用 Runner(Project runners、Group runners 或 Instance runners 均可)。如果该 Runner 沒有勾选“Run untagged jobs(运行无标签任务)”,请记下它显示的标签名称(例如 docker),后续需要在配置文件的 tags 字段中填写该标签,否则流水线会一直处于 Pending(挂起)状态。
步骤 2:在仓库根目录创建 .gitlab-ci.yml
最推荐的方式是使用 Docker 执行器配合官方轻量级镜像 python:3.11-slim。在项目根目录新建 .gitlab-ci.yml,编写以下完整配置:
default:
image: python:3.11-slim
cache:
key:
files:
- requirements.txt
paths:
- .cache/pip
- .venv/
before_script:
- python -V
- python -m venv .venv
- source .venv/bin/activate
- pip install --upgrade pip
- pip install -r requirements.txt
stages:
- test
- run_script
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
PYTHONUNBUFFERED: "1"
TARGET_ENV: "production"
MIN_SCORE: "80"
unit_test_job:
stage: test
script:
- pytest tests/
execute_report_job:
stage: run_script
script:
- python scripts/check_report.py
artifacts:
paths:
- output/summary.json
expire_in: 7 days
when: always
步骤 3:理解配置中的关键设置
上述配置文件中包含了保障 Python 脚本稳定运行的四个关键细节:
PYTHONUNBUFFERED: "1":Python 默认会对标准输出进行缓冲,如果脚本运行时间较长,GitLab 的 Job 日志页面可能迟迟看不到输出。将该环境变量设为1(或在命令行加python -u)可以让print()内容实时刷新到流水线控制台。PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip":GitLab CI 的cache机制只能缓存项目工作目录($CI_PROJECT_DIR)内部的路径。而pip默认将缓存放在用户主目录~/.cache/pip下,因此必须通过PIP_CACHE_DIR将缓存改写到项目目录内,并连同虚拟环境目录.venv/一起加入缓存。cache:key:files:以requirements.txt的文件内容哈希作为缓存键。只要依赖文件未修改,后续流水线可直接复用已安装好的.venv/,免去重复下载编译第三方包的时间。artifacts:Docker 容器在 Job 结束后会被立即销毁,脚本生成的output/summary.json默认随之丢失。通过声明artifacts:paths,Runner 会在容器销毁前将该文件打包上传至 GitLab 服务端保存 7 天,设置when: always表示即使脚本失败也上传已生成的报告,方便排查原因。
步骤 4:提交代码并触发流水线
在本地终端项目的根目录下,将新编写的脚本与配置文件提交并推送到 GitLab 远程仓库:
git add .gitlab-ci.yml requirements.txt scripts/check_report.py tests/test_report.py
git commit -m "ci: 添加Python脚本自动执行流水线"
git push origin main
步骤 5:查看执行结果与下载产物
推送完成后,在 GitLab 项目左侧菜单点击 Build(构建) > Pipelines(流水线),可以看到刚触发的一条流水线正在运行。点击进入 execute_report_job 查看控制台实时日志。正常情况下,日志末尾会显示类似下方的输出(以下为示例输出):
$ source .venv/bin/activate
$ pip install -r requirements.txt
Requirement already satisfied: requests==2.31.0 in ./.venv/lib/python3.11/site-packages (from -r requirements.txt (line 1))
Requirement already satisfied: pytest==8.1.1 in ./.venv/lib/python3.11/site-packages (from -r requirements.txt (line 2))
$ python scripts/check_report.py
[INFO] 报告已生成: output/summary.json,当前环境: production,得分: 85
Uploading artifacts for successful job
Uploading artifacts...
output/summary.json: found 1 matching artifact files and directories
Uploading artifacts as "archive" to coordinator... 201 Created
Job succeeded
在 Job 详情页面的右侧边栏中,会出现 Job artifacts 区域,点击 Keep、Download 或 Browse 即可直接查看或下载 output/summary.json。
三、Docker 执行器与 Shell 执行器的配置差异
在实际项目中,GitLab Runner 最常被注册为 Docker 执行器(Executor) 或 Shell 执行器。两者的运行机制不同,编写 .gitlab-ci.yml 的方式也有明显区别。
如果团队的 GitLab Runner 采用的是 Shell 执行器,配置文件中的 image: python:3.11-slim 会被直接忽略,Runner 会以宿主机上的 gitlab-runner 系统用户身份在本地目录运行命令。在这种场景下,如果直接运行 pip install -r requirements.txt,不仅可能因为没有系统目录写权限而报错 Permission denied,还会把第三方库安装进宿主机全局或用户级目录,导致不同项目的流水线互相覆盖依赖版本。
因此,在 Shell 执行器下运行 Python 脚本时,应当显式调用宿主机上的 python3 命令创建项目级虚拟环境,写法如下:
execute_report_shell_job:
stage: run_script
tags:
- linux-shell
before_script:
- python3 -m venv .venv
- source .venv/bin/activate
- pip install --upgrade pip
- pip install -r requirements.txt
script:
- python scripts/check_report.py
四、向 Python 脚本传递参数、密钥与定时触发
许多 Python 脚本需要访问外部接口密钥、数据库连接串,或者在每天固定时间运行巡检任务。这类敏感信息不能硬编码在 scripts/check_report.py 或 .gitlab-ci.yml 中。
1. 注入敏感环境变量
进入项目左侧菜单的 Settings > CI/CD > Variables,点击 Add variable。例如添加一个名为 API_SECRET_TOKEN 的变量,勾选 Mask variable(在日志中隐藏变量值)。保存后,GitLab 会在流水线运行时自动将其注入到环境变量中,Python 脚本直接通过 os.environ.get("API_SECRET_TOKEN") 即可读取;也可以在 .gitlab-ci.yml 中将其作为命令行参数传给脚本:
execute_report_job:
stage: run_script
script:
- python scripts/check_report.py --env "$TARGET_ENV" --token "$API_SECRET_TOKEN"
2. 配置定时执行(Pipeline Schedules)
如果希望 Python 脚本除了在代码提交时运行,还能每天凌晨自动执行一次,可以在项目左侧菜单进入 Build > Pipeline schedules,点击 New schedule,填写 Cron 表达式(例如 0 2 * * * 表示每天凌晨 2 点)并选择目标分支。若某个脚本任务只希望在定时任务触发时才运行,可以在 Job 中加上 rules 限制:
daily_check_job:
stage: run_script
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
script:
- python scripts/check_report.py
五、常见问题与报错排查
在把本地能够正常运行的 Python 脚本迁移到 GitLab CI 时,最常遇到以下三类报错,可按具体表现逐一排查解决。
| 报错表现 | 产生原因 | 修复方法 |
|---|---|---|
ModuleNotFoundError: No module named 'xxx'(导入本项目自定义模块失败) |
执行 python scripts/check_report.py 时,Python 默认将 scripts/ 目录而非项目根目录加入 sys.path,导致无法导入根目录下的其他包。 |
在 variables 中设置 PYTHONPATH: "$CI_PROJECT_DIR",或改用模块方式执行:python -m scripts.check_report。 |
gcc: command not found 或编译 C 扩展包失败 |
使用了 python:3.11-slim 或 alpine 等精简镜像,缺少编译部分 Python 包所需的 C 编译器及头文件。 |
优先升级 pip 以获取预编译的 manylinux wheel 包;若仍需编译,在 before_script 开头加 apt-get update && apt-get install -y build-essential(尽量避免使用 alpine 镜像运行含 C 扩展的 Python 项目)。 |
内网环境下 pip install 超时或连接失败 |
Runner 容器所处的内网无法直连官方 PyPI 源,或者自建镜像源使用了自签名证书。 | 在 variables 中配置变量 PIP_INDEX_URL 指向内网或国内镜像源,必要时添加 PIP_TRUSTED_HOST。 |
按照上述结构完成配置后,每次向仓库推送代码或到达预设定时任务时间,GitLab CI 都会在隔离环境中自动拉取依赖并运行指定的 Python 脚本,同时将控制台日志和产物文件完整保存下来。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













