uv 与 Coiled 集成实战:把 PEP 723 自包含 Python 脚本一键提交到 Serverless 云执行
本文基于 uv 仓库官方指南 docs/guides/integration/coiled.md 展开,讲解如何以 uv 的 PEP 723 内联脚本元数据为基础,将本地可运行的 Python 脚本通过 Coiled 平台提交到 AWS/GCP/Azure 的无服务器云环境中执行,并结合仓库源码剖析 uv 解析内联元数据的底层机制,帮助你掌握「本地写一次脚本、云端直接跑」的完整工作流。
一、整体思路:自包含脚本 + Serverless 云平台
Coiled 是一个 Serverless、以用户体验为导向的云计算平台,可以便捷地在 AWS、GCP 和 Azure 的云上硬件上运行代码。uv 与 Coiled 结合的核心思路是:
- 依赖管理交给 uv:脚本通过 PEP 723 内联元数据声明依赖,
uv run在任何机器上都会自动创建虚拟环境并安装依赖,脚本本身完全自包含; - 云端执行交给 Coiled:脚本里加两行
# COILED注释即可指定容器镜像和云区域,再用coiled batch run把uv run命令提交到云端 VM 执行。
适合的场景包括:
- 处理大量托管在云上的数据;
- 需要 GPU 或大内存等加速/增强硬件;
- 需要把同一个脚本针对成百上千个不同输入并行执行。
二、用 uv 管理脚本依赖:PEP 723 内联元数据
指南以如下脚本为例(任何 Python 脚本都可以按同样方式接入):
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "pandas",
# "pyarrow",
# "s3fs",
# ]
# ///
import pandas as pd
df = pd.read_parquet(
"s3://coiled-data/uber/part.0.parquet",
storage_options={"anon": True},
)
print(df.head())
该脚本用 pandas 从 S3 公共桶加载一个 Parquet 文件并打印前几行,通过 PEP 723 内联脚本元数据(# /// script ... # /// 注释块内的 TOML)枚举依赖。本地运行只需:
$ uv run process.py
uv 会自动创建虚拟环境并安装声明的依赖,无需手动 venv/pip install。关于内联元数据的完整用法(uv init --script 初始化、uv add --script 添加依赖等),见 脚本运行指南。
源码视角:uv 如何解析内联元数据
内联元数据的解析实现在独立的 uv-scripts crate 中,值得理解的关键点:
- 定位
script块:ScriptTag::parse 用memchr快速查找# /// script起始标记(要求它是文件第一行或紧跟换行之后的行),逐行剥离前导#,再从末尾向前找到恰好为# ///的闭合标记,最终把文件拆分为 prelude(shebang 等前导内容)、metadata(TOML 块)、postlude(实际 Python 代码)三段。 - 元数据模型:Pep723Metadata 结构体定义了脚本可携带的字段:
dependencies(PEP 508 依赖列表)、requires-python(版本约束)以及tool表。其中 ToolUv 还允许在脚本内声明tool.uv配置(如index、sources、exclude-newer等),这使得「私有源」「可复现锁定」等设置也能随脚本一起分发。 - 严格的错误提示:Pep723Error 针对常见笔误给出精确诊断,例如开闭标记不配对(
UnclosedBlock)、闭合标记后带有多余内容(UnclosedBlockTrailingContent)、一个文件中出现多个script块(DuplicateBlock)等;配套的单测(同文件tests模块,如 no_closing_pragma)覆盖了这些边界情况。 - 多种输入来源:Pep723Item 支持从磁盘(
Script)、标准输入(Stdin)和远程 URL(Remote)三种途径获取 PEP 723 脚本。Remote分支说明uv run https://.../script.py这类远程脚本执行是被一等支持的——crates/uv/src/commands/project/run.rs 中存在PendingRemoteRunCommand/PythonRemote等实现路径,仓库还带有针对该行为的测试脚本 scripts/uv-run-remote-script-test.py。这意味着「自包含脚本」天然适合跨机器传输和远端触发执行,正是接入 Coiled 的前提。
三、把脚本提交到 Coiled 云端执行
1. 认证
$ uvx coiled login
uvx 是 uv tool run 的别名(可在 README 中确认:uvx 在临时环境中运行工具),因此这条命令会临时拉取 Coiled CLI 并完成登录;没有账户时会被引导免费创建一个。
2. 用两行注释声明云端运行环境
在脚本顶部加入:
# COILED container ghcr.io/astral-sh/uv:debian-slim
# COILED region us-east-2
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "pandas",
# "pyarrow",
# "s3fs",
# ]
# ///
import pandas as pd
df = pd.read_parquet(
"s3://coiled-data/uber/part.0.parquet",
storage_options={"anon": True},
)
print(df.head())
两条注释的含义:
# COILED container ghcr.io/astral-sh/uv:debian-slim:指定 Coiled 使用官方 uv Docker 镜像运行脚本,保证云端 VM 里自带 uv。这个镜像属于 uv 的「衍生镜像」系列(基于debian:trixie-slim),完整标签列表与版本 pinning 建议见 Docker 集成指南;# COILED region us-east-2:指定在 AWS 的us-east-2区域运行——示例数据文件恰好存放在该区域,可避免跨区数据出口(egress)流量。
提示:Coiled 同时支持 AWS、GCP 和 Azure,以上示例假设使用 AWS。新用户默认获得运行在 AWS 上的免费账户;如果不使用 AWS,可换成对应云厂商的有效
region值,或直接删掉region这一行。
3. 提交批处理任务
用 coiled batch run 在云端执行 uv run 命令:
$ uvx coiled batch run \
uv run process.py
执行后,原本在本地运行的同一套流程(解析内联元数据 → 创建环境 → 安装依赖 → 运行脚本)会发生在 AWS 的远程云 VM 上。
四、监控与管理批处理任务
- Web UI:在 Coiled 云控制台页面查看任务进度;
- 命令行:使用以下命令在终端跟踪任务:
coiled batch status:查看任务状态;coiled batch wait:阻塞等待任务结束;coiled batch logs:查看任务日志。
此外,还可以指定更多云端资源参数,例如:
- 实例类型(默认是一台 4 核 CPU、16 GiB 内存的 VM);
- 磁盘大小;
- 是否使用 spot(竞价)实例。
更多参数细节请参考 Coiled Batch 官方文档。
五、增强脚本可移植性与可复现性的配套手段
围绕「同一份脚本在任意机器上行为一致」这一目标,uv 提供了几个可与 Coiled 流程直接组合的能力(详见 docs/guides/scripts.md):
- 锁定依赖:对 PEP 723 脚本执行
uv lock --script process.py,会在脚本旁生成.lock锁文件,后续的uv run --script等命令复用锁定结果,保证云端与本地安装到相同版本; - 时间冻结(exclude-newer):在内联元数据的
[tool.uv]表里声明exclude-newer(RFC 3339 时间戳),限定只解析某个日期之前发布的发行版,进一步提升历史可复现性——对应 uv-scripts 中ToolUv对全局解析选项的透传支持; - shebang 可执行脚本:加上
#!/usr/bin/env -S uv run --script首行并chmod +x后,脚本可脱离uv run直接执行,方便被其他调度系统(包括云端 shell 命令)直接调用; - 容器内使用 uv 的最佳实践:如果希望把自定义环境固化成镜像而不只是引用官方镜像,可参考 Docker 指南 中的多阶段构建、缓存挂载与中间层拆分等优化。
六、适用前提与限制
- 需要本地已安装 uv(
uv run/uvx可用); - 需要可访问的 Coiled 账户,且示例数据
s3://coiled-data/uber/part.0.parquet为公共可读对象,换成自己的数据时注意相应的访问凭证配置; # COILED注释行只被 Coiled 解释,uv 将其视为普通注释,因此同一份脚本本地、云端行为一致;- 区域选择会影响数据出口费用,建议把任务
region与数据所在区域对齐。
小结
整条链路只有三步:用 # /// script 内联元数据声明依赖,让脚本自包含;加两行 # COILED 注释指定官方 uv 镜像与云区域;执行 uvx coiled batch run uv run process.py 提交到云端。从仓库源码看,uv-scripts 对 PEP 723 元数据块的严格解析与标准化错误处理、以及 run 命令 对本地/stdin/远程脚本三类输入的统一支持,是「脚本写一次、到处可跑」这一工作流得以成立的底层保障。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00