从一个小仓库准备可复用的编程环境
本文目录
先让准备步骤结束,再启动服务。一份有用的环境准备包,应包含源输入、能重建产物的命令、会真实拒绝错误情形的检查,以及独立的启动、检查和关闭方式。服务打印“正在监听”,只是其中一步。
本教程提供一个完整的原创项目 label-lab:将两行 CSV 确定性地生成为 JSON catalog,再通过回环地址提供服务。英文作者曾从源码压缩包出发,在两个新建空目录中运行它。下文的本地结果来自对原创教学代码的实际执行,不是 Codex Cloud 运行、客户记录或模型基准测试。本中文稿引用这些既有结果,没有重新运行项目。
取得完整源码和这个小项目的约定
下载共享的 label-lab.zip 并解压。压缩包在 label-lab/ 下提供整个项目,包括 README:
label-lab/
.gitignore
README.md
data/labels.csv
scripts/build_catalog.py
scripts/check_catalog.py
scripts/prepare.py
scripts/serve_catalog.py
scripts/lifecycle.py
scripts/wrong_prepare.py
tests/test_catalog.py
本项目不需要下载软件包、创建账号、使用密钥或调用外部服务。所附生命周期辅助程序要求 POSIX 系统及 Python 3.9 或更高版本;它用 selectors 等待子进程输出管道。先核对你的机器实际有哪些运行时,不要假定处处都有本文下方记录的本地版本。本地策略还需要允许绑定回环套接字。
完整的输入 CSV 如下:
id,label
alpha,Alpha
beta,Beta
输出约定恰好是这两个条目,按 ID 排序。规范文件只有下面这一行,末尾再加一个 LF:
[{"id":"alpha","label":"Alpha"},{"id":"beta","label":"Beta"}]
构建脚本检查表头和各行,拒绝重复 ID,按 ID 排序后写出 JSON。检查器同时核对两个条目的确切含义和规范字节。这些规则特意限定于本教学样例,不是通用 catalog 格式。
执行会结束的准备步骤,并等待它返回
在解压后的 label-lab 目录中打开终端。先查看将使用哪个解释器,再运行准备:
python3 --version
python3 scripts/prepare.py
只有准备步骤退出码为 0,才继续操作。完整命令文件 使用同一个解释器执行三个会结束的操作:
scripts/build_catalog.py
scripts/check_catalog.py
-m unittest discover -s tests -v
每个操作等待子进程的时间都有上限;某一步失败,准备就停止。这个命令不启动服务,成功时最后输出:
preparation complete; no service started
此时生成了 build/catalog.json。完整转换器 和检查器 都在包内,因此结果不依赖作者工作区遗留的文件。构建目录可以重新生成,已被 .gitignore 排除;需要保留的是原始 CSV 和脚本。
三个命令行行为测试 不只检查路径是否存在。它们实际构建有效的两行 catalog 并比对内容,让真实转换器拒绝重复的 alpha,也让检查器拒绝缺失的 catalog。输入和输出均放在临时目录。错误输入被正确拒绝,表示负例检查通过,不表示构建成功。
单独启动,确认就绪,再关闭子进程
准备成功后运行:
python3 scripts/lifecycle.py
生命周期辅助程序 只在 127.0.0.1 启动一个目录服务子进程。它传入端口 0,由操作系统选择可用端口,不抢占其他进程使用的端口。独立运行服务时,若不传端口,默认是 8765;本次复现没有使用这个默认值。
辅助程序先在限定时间内等待监听公告,再分别核对两类响应:
| 请求 | 本样例要求的响应 |
|---|---|
GET /health |
HTTP 200,正文恰好为 ok |
GET /catalog |
HTTP 200,字节与已检查的 build/catalog.json 完全一致 |
本地客户端禁用代理,只连接公告中的回环地址。catalog 缺失或不符合约定时,服务返回 HTTP 503 和 catalog unavailable;它不会编出空目录,也不会报告已经就绪。
辅助程序在 finally 中终止并等待自己启动的子进程。子进程若未及时退出,还有带时间上限的强制结束与等待步骤。它不会搜索或终止某个端口背后的其他进程。结果会记录子进程退出状态和端口关闭探测。两次成功的本地执行均观察到服务退出码 0、childStopped: true 和 portClosedAfterStop: true。
这是一个会结束的启动/检查/关闭练习,返回后特意不保留运行中的服务。如果想手工交互查看服务,可在另一个终端运行:
python3 scripts/serve_catalog.py --port 0
使用该进程自己公告的端口,再在同一终端按 Ctrl-C 关闭它。真正需要服务持续运行的工作,应保留受控的服务会话,并另行定义关闭方式。不要把这个有限生命周期练习当成守护进程启动器。
看清前台服务为什么应放在准备步骤之外
下面是故意编写的完整错误顺序:
python3 scripts/serve_catalog.py --port 0
python3 scripts/build_catalog.py
python3 scripts/check_catalog.py
在全新目录中,第一个命令会一直占据前台。只要它还在运行,后面的构建和检查就没有执行机会。套接字可能在监听,却没有可以成功提供的 catalog。
这是作者构造的流程错误。项目提供了一个有限时间的演示程序,让你观察这个顺序而不遗留进程。只在没有 build/catalog.json 的全新副本中运行它:
python3 scripts/wrong_prepare.py
它等待自己的服务一秒,记录下一步尚未执行,再在 finally 中终止并回收子进程。作者的本地副本 A 观察到以下结果,字段和数值保留英文输出:
{"authoredCounterexample":true,"buildStepReached":false,"catalogExists":false,"childStopped":true,"foregroundServerBlockedNextStep":true,"serverExit":0}
演示退出码为 0,表示它观察到了预期的错误顺序,并完成清理,不表示准备已完成。在同一尚未准备的副本中,python3 scripts/lifecycle.py --timeout 0.5 观察到 HTTP 503 后退出 1;它也停止了子进程,并观察到端口已关闭。
修复方式就是前面的有限顺序:先运行 prepare.py,等待退出 0,再运行 lifecycle.py。这条顺序在副本 A 中实际完成了构建、检查、测试和目录服务读取;副本 B 也单独成功。B 来自重新解压的源码包,没有复制 A 生成的文件。
按实际范围理解两份副本的结果
复现请求的运行时是 /usr/bin/python3。公开文件用 <LOCAL_PYTHON_EXECUTABLE> 代表当时记录的本机解释器安装路径;其报告版本为 Python 3.9.6,系统为 macOS 26.5.2 arm64。两处工作区都是新建临时目录,解压同一源码包之前为空,结束后均已移除。公开命令记录 保留运行时、命令语义、stdout/stderr 和退出码,同时将机器特定路径重映射为声明过的占位符。这是公开投影,不是与原始输出逐字节相同的文件;制作投影没有重跑项目,本次翻译也没有重跑。
| 观察项 | 作者本地副本 A | 作者本地副本 B |
|---|---|---|
| 准备前没有 catalog | 是 | 是 |
| 有限构建、检查和三个行为测试 | 退出 0 | 退出 0 |
| 测试中重复 ID 的命令行结果 | 退出 2;duplicate id: alpha;未创建输出 |
相同 |
| 测试中缺失 catalog 的检查结果 | 退出 1;报告缺失错误 | 相同 |
| 准备后的健康/目录响应 | HTTP 200 / HTTP 200 | HTTP 200 / HTTP 200 |
| catalog 字节数 | 62 | 62 |
| 子进程停止且回环端口关闭 | 已观察到 | 已观察到 |
两份副本生成了相同的 SHA-256:
b82daf83bcd381d0dc86acf390f89197677e4988441b487d0ab45f2ae3759b90
实际 catalog 文件 保留这 62 个真实字节。中文公开复现说明 记录了命令和首次失败:默认本地沙箱拒绝绑定回环地址,后来的成功本地执行另行获准使用回环连接。这个权限失败,与 CSV 验证失败或云服务结果是不同的事情。
两份同机干净目录只证明该运行时下的本地重建,不证明所有操作系统都兼容,也不证明某个服务商提供相同运行时或已发布云环境具有相同状态。
此外,独立技术审阅者另在一个新的干净本地副本中复现了项目。那是额外的一次独立执行,不是重新观察作者已删除的 A/B 历史目录,也不是独立跑了两份新副本。共享公开结果 JSON 记录的仍是作者 A/B 两次执行,不能当作三次原始日志。本中文稿由英文原作者翻译,译者自查不等于独立审阅。
将准备包对应到文档说明的云端角色
OpenAI 所引的 Cloud environments 指南把用于依赖和开发资产的 Install script,与用于启动服务并检查就绪的 Start skill 分开。若另获云端配置授权,可向设置流程说明本仓库及已验证运行时:前者使用会结束的准备命令,后者参照 README 中的服务说明。生命周期辅助程序会检查并关闭服务,不会留下持续运行的服务。
指南说明,发布会保存供新任务使用的已准备文件;已有任务保留各自保存的状态。更新可复用设置后,要重新发布,并启动新任务使用更新,不能假定已有任务自动取得新设置。所引指南也列明当时云环境不支持计算机/浏览器操作。本例只需要终端命令与回环 HTTP,不依赖浏览器自动化。这是文档映射,不是已测试的云端配置,也没有猜造配置文件格式。本工作没有创建云环境或云任务。
将真实故障报告与教学错误分开
一则公开配置提问询问安装与启动应如何衔接;另一份个人云端任务卡住的报告描述了几次小任务成功之后出现的问题。既有研究保留了互相冲突的日期信息,没有验证根因或整体可靠性。本教程中有时间限制的前台服务反例,不是对那份报告的诊断或修复方案。
调整准备包时,保留原始项目文件和准确的命令结果。准备失败,就先修复并重跑失败的有限步骤,再启动服务;健康检查不可用,就检查 catalog 和服务结果,不能把“端口在监听”当成完成。你可以打字或口述环境需求;使用转写时,要核对路径、选项和否定是否保留。输入方式本身不证明结果更好。
这个完整本地准备包交给下一个读者的是可重建的实物:完整输入与代码、会结束的准备命令、独立受控的服务和实际重建证据。后续任何云端配置,都需要自己的真实观察结果。