pycamp:零依赖构建 Python 闯关训练营

Python 训练营PythonnginxSSERAG代码沙箱
2026-10-11 · 1123 字 · 约 3 分钟
本文目录(8 节)

Python 闯关训练营 是一个在线 Python 学习站点:用户在页面上闯关答题、直接在浏览器里跑代码、遇到问题还能和 AI 陪练对话。整条链路没有引入任何一个第三方运行时依赖,全部基于 Python 标准库 + nginx 原生能力。

💡 一句话定位: 「纯静态前端 + 标准库后端微服务 + nginx 智能网关」,AI 能力全部由网关层代理,密钥不出服务器。
  • 访问层 — 纯静态 SPA · 原生 HTML/CSS/JS 单文件交付,无框架、无构建工具,闯关交互全在浏览器端完成
  • 网关层 — nginx · TLS 终结、静态缓存、limit_req 按 IP 限流、Origin 白名单防脚本直调、三路 AI 反代(密钥托管 / 密钥透传)
  • 服务层 — Python 标准库微服务 ×2 · 代码执行沙箱(127.0.0.1:8021,按 IP 限额)+ AI 学习服务(127.0.0.1:8022,RAG 答疑 / 代码批改 / SSE 流式)
  • 模型层 — 多通道互备 · 智谱 GLM(免费额度,密钥服务端托管)、DeepSeek(用户自带 Key 透传)、OpenCode Zen(免费模型池透传)
图 1 · pycamp 的技术组成(每一层都不引入第三方依赖)
图 1 · pycamp 的技术组成(每一层都不引入第三方依赖)pycampWeb 前端单页 SPA 零框架Pyodide 浏览器内跑多源 CDN 自动切换后端微服务pycamp-runner 沙箱pycamp-learn RAGsite-ask 站内问答nginx 网关托管 Key 注入限流与 Origin 校验SSE 流式透传课程数据29 个关卡239 个知识块错误画像 SQLite

整体架构#

text
浏览器
  │
  ▼
nginx (80/443, TLS 终结)
  ├── /pycamp/            → 静态 SPA (/www/wwwroot/pycamp)
  ├── /pycamp/api/        → 127.0.0.1:8021  代码执行沙箱
  ├── /pycamp/api/learn/  → 127.0.0.1:8022  AI 学习服务 (RAG)
  ├── /pycamp/api/ai/zhipu/ → open.bigmodel.cn   (密钥托管)
  ├── /pycamp/api/ai/zen/   → opencode.ai/zen    (密钥透传)
  └── /pycamp/api/ai/       → api.deepseek.com   (密钥透传)

技术栈清单#

层选型说明
前端纯静态 HTML/CSS/JS 单文件 SPA无框架、无构建步骤,index.html 单文件交付
沙箱后端Python 标准库 ThreadingHTTPServer端口 8021,仅监听 127.0.0.1,执行用户提交的代码
学习服务标准库 HTTP 服务 + RAG端口 8022,答疑 / 代码批改 / 错误画像,SSE 流式输出
AI 模型智谱 GLM / DeepSeek / OpenCode Zen免费额度优先,多通道互为备份
网关nginx 反向代理 + limit_reqTLS、静态缓存、限流、AI 反代

几个关键设计#

1. AI 密钥不出前端:nginx 托管注入#

智谱通道的 API Key 只存在于 nginx 配置里,由网关注入 Authorization 头,前端代码不含任何密钥:

nginx
location ^~ /pycamp/api/ai/zhipu/ {
    if ($pycamp_zhipu_ok = 0) { return 403; }   # Origin 白名单
    limit_req zone=pycamp_ai_zhipu burst=60 nodelay;
    proxy_pass https://open.bigmodel.cn/api/paas/v4/;
    proxy_set_header Authorization "Bearer <server-side-key>";
    proxy_buffering off;          # SSE 必须关缓冲
}

DeepSeek / Zen 通道则走透传模式:用户在前端填自己的 Key,服务器不保存、不解析,只负责转发绕过 CORS 限制。

2. SSE 流式输出的两个坑#

  • proxy_buffering off:不关的话回答会整段卡到最后才一次性出现;
  • 长超时:proxy_read_timeout 300s,模型思考久一点不会被网关掐断。

3. 滥用防护:三层闸门#

  • Origin 白名单:只放行本站页面发起的请求,空 Origin(curl / 脚本直调)一律 403;
  • 按 IP 限流:托管通道每分钟 30 次、burst 60,防脚本刷免费额度;
  • 真实 IP 透传:沙箱服务按 IP 计配额,nginx 必须传 X-Real-IP,否则所有人共用 127.0.0.1 的份额。
经验:标准库实现并非炫技——学习类工具站的并发量级很小,零依赖意味着零供应链风险、零版本升级负担,部署就是 python3 server.py 一行命令。

踩过的坑#

  • nginx 正则 location(静态资源缓存那条)会抢走前缀匹配,沙箱路由必须加 ^~;
  • Zen 官方不开放 CORS(预检 404),所以必须有网关转发这一层,浏览器无法直连;
  • 限流要区分「托管密钥」和「用户自带密钥」两种严格程度,前者更严。

延伸阅读#

训练营的 AI 陪练靠一套自研检索(29 关切 239 个知识块)来定位答案。检索准不准直接决定回答质量,所以我们给它补了一套 237 题的评测——并因此发现了两个真 bug、选出了三个优化、同时否决了两个"看起来更高级"的想法:

👉 给自研 RAG 做评测:三个优化是怎么被数据选出来的

🏷 Python🏷 nginx🏷 SSE🏷 RAG🏷 代码沙箱
💬 问我 只依据站内资料作答
可以问这个站点的技术内容,例如「pycamp 的代码沙箱怎么做的」「为什么不直接用向量检索」。