使用 jsr:@langchain/pyodide-sandbox 构建 Python 安全沙箱(完整入门教程)

适用于:

  • LLM / Agent 执行不可信 Python 代码
  • 在线 Python 运行环境
  • LangChain / 自动化工具沙箱
  • 多租户系统安全执行

一、背景介绍

在 LLM Agent、在线代码执行、插件系统等场景中,我们经常面临一个问题:

如何安全地执行用户提供的 Python 代码?

传统方案(exec / 子进程 / Docker)要么不安全、要么太重。

LangChain 官方给出了一种更优雅的方案:

Pyodide + Deno Sandbox

其中核心组件就是:

复制代码
jsr:@langchain/pyodide-sandbox

它允许我们在 WebAssembly(WASM)级别 安全执行 Python 代码,并且具备:

  • 强隔离
  • 权限控制
  • 低资源占用
  • 易于集成 Agent / LangChain

二、什么是 jsr:@langchain/pyodide-sandbox?

2.1 核心技术栈

组件 作用
Pyodide Python → WebAssembly
Deno 沙箱运行时
WASM 系统级隔离
micropip Python 包安装

整体结构:

复制代码
Python Code
   ↓
Pyodide (WASM)
   ↓
Deno Sandbox
   ↓
Host OS(隔离)

2.2 为什么不用 Docker?

对比 Docker Pyodide Sandbox
启动速度 ⚡ 极快
资源占用
安全粒度 容器级 WASM 级
Agent 集成 一般 非常友好

三、环境准备

3.1 安装 Deno

bash 复制代码
curl -fsSL https://deno.land/install.sh | sh

加入环境变量:

bash 复制代码
export PATH="$HOME/.deno/bin:$PATH"

验证:

bash 复制代码
deno --version

四、最基础用法(CLI)

4.1 执行 Python 代码

bash 复制代码
deno run -A jsr:@langchain/pyodide-sandbox \
  -c "print('Hello, World')"

输出:

text 复制代码
{"stdout":"Hello, World","stderr":null,"result":null,"success":true,"sessionMetadata":{"created":"2026-01-22T02:13:43.619Z","lastModified":"2026-01-22T02:13:43.660Z","packages":[]}}

4.2 执行计算

bash 复制代码
deno run -A jsr:@langchain/pyodide-sandbox \
  -c "print(2 + 3)"
复制代码
{"stdout":"5","stderr":null,"result":null,"success":true,"sessionMetadata":{"created":"2026-01-22T02:09:58.747Z","lastModified":"2026-01-22T02:09:58.794Z","packages":[]}}

五、自动安装 Python 包(micropip)

Pyodide 无需 pip / venv ,而是使用 micropip

5.1 使用 numpy 示例

bash 复制代码
deno run -A jsr:@langchain/pyodide-sandbox \
  -c "import numpy as np; print(np.arange(5))"

首次执行会看到:

text 复制代码
{"stdout":"Loading numpyDidn't find package numpy-2.0.2-cp312-cp312-pyodide_2024_0_wasm32.whl locally, attempting to load from https://cdn.jsdelivr.net/pyodide/v0.27.7/full/Package numpy-2.0.2-cp312-cp312-pyodide_2024_0_wasm32.whl loaded from https://cdn.jsdelivr.net/pyodide/v0.27.7/full/, caching the wheel in node_modules for future use.Loaded numpy[0 1 2 3 4]","stderr":null,"result":null,"success":true,"sessionMetadata":{"created":"2026-01-22T02:14:13.300Z","lastModified":"2026-01-22T02:14:17.036Z","packages":["numpy"]}}

这是 正常行为,表示:

  • Pyodide 正在下载依赖
  • 下载完成后会缓存到 node_modules
  • 后续执行不会再下载

六、Stateful 会话(保持执行状态)

默认情况下,每次执行是 无状态的

如果你希望多次执行共享变量,需要开启 stateful 模式


6.1 创建 state

bash 复制代码
deno run -A jsr:@langchain/pyodide-sandbox \
  -s -c "x = 42"

会返回 sessionBytes

bash 复制代码
{"stdout":null,"stderr":null,"result":null,"success":true,"sessionBytes":[128,4,149,168,0,0,0,0,0,0,0,140,10,100,105,108,108,46,95,100,105,108,108,148,140,14,95,105,109,112,111,114,116,95,109,111,100,117,108,101,148,147,148,140,8,95,95,109,97,105,110,95,95,148,133,148,82,148,125,148,40,140,8,95,95,110,97,109,101,95,95,148,104,3,140,7,95,95,100,111,99,95,95,148,78,140,11,95,95,112,97,99,107,97,103,101,95,95,148,78,140,8,95,95,115,112,101,99,95,95,148,78,140,15,95,95,97,110,110,111,116,97,116,105,111,110,115,95,95,148,125,148,140,13,95,112,121,111,100,105,100,101,95,99,111,114,101,148,104,2,140,13,95,112,121,111,100,105,100,101,95,99,111,114,101,148,133,148,82,148,140,1,120,148,75,42,117,98,46],"sessionMetadata":{"created":"2026-01-22T02:14:55.543Z","lastModified":"2026-01-22T02:14:56.955Z","packages":["dill"]}}

6.2 恢复 state

jsr:@langchain/pyodide-sandbox 的 stateful 会话由 两部分组成

字段 作用
sessionBytes Python VM 的二进制快照(dill 序列化)
sessionMetadata 会话上下文(创建时间 / 包信息 / 兼容性校验)

CLI 在恢复 session 时需要:

text 复制代码
sessionBytes   → 还原 Python 对象
sessionMetadata → 校验 & 环境一致性
bash 复制代码
deno run -A jsr:@langchain/pyodide-sandbox \
  -s -b '<sessionBytes>' \
  -m '<sessionMetadata>' \
  -c "print(x)"

例子

bash 复制代码
deno run -A jsr:@langchain/pyodide-sandbox \
  -s \
  -b '[128,4,149,168,0,0,0,0,0,0,0,140,10,100,105,108,108,46,95,100,105,108,108,148,140,14,95,105,109,112,111,114,116,95,109,111,100,117,108,101,148,147,148,140,8,95,95,109,97,105,110,95,95,148,133,148,82,148,125,148,40,140,8,95,95,110,97,109,101,95,95,148,104,3,140,7,95,95,100,111,99,95,95,148,78,140,11,95,95,112,97,99,107,97,103,101,95,95,148,78,140,8,95,95,115,112,101,99,95,95,148,78,140,15,95,95,97,110,110,111,116,97,116,105,111,110,115,95,95,148,125,148,140,13,95,112,121,111,100,105,100,101,95,99,111,114,101,148,104,2,140,13,95,112,121,111,100,105,100,101,95,99,111,114,101,148,133,148,82,148,140,1,120,148,75,42,117,98,46]' \
  -m '{"created":"2026-01-22T02:14:55.543Z","lastModified":"2026-01-22T02:14:56.955Z","packages":["dill"]}' \
  -c "print(x)"

输出:

text 复制代码
{"stdout":"42","stderr":null,"result":null,"success":true,"sessionBytes":[128,4,149,168,0,0,0,0,0,0,0,140,10,100,105,108,108,46,95,100,105,108,108,148,140,14,95,105,109,112,111,114,116,95,109,111,100,117,108,101,148,147,148,140,8,95,95,109,97,105,110,95,95,148,133,148,82,148,125,148,40,140,8,95,95,110,97,109,101,95,95,148,104,3,140,7,95,95,100,111,99,95,95,148,78,140,11,95,95,112,97,99,107,97,103,101,95,95,148,78,140,8,95,95,115,112,101,99,95,95,148,78,140,15,95,95,97,110,110,111,116,97,116,105,111,110,115,95,95,148,125,148,140,13,95,112,121,111,100,105,100,101,95,99,111,114,101,148,104,2,140,13,95,112,121,111,100,105,100,101,95,99,111,114,101,148,133,148,82,148,140,1,120,148,75,42,117,98,46],"sessionMetadata":{"created":"2026-01-22T02:14:55.543Z","lastModified":"2026-01-22T02:18:31.879Z","packages":["dill"]}}

七、Python 正确执行模板(非常重要)

⚠️ 很多人踩坑就在这里

❌ 错误写法

python 复制代码
2 + 3

或者:

python 复制代码
print(2 + 3)

这样不会返回 result,只会进 stdout。


✅ 正确写法(标准模板)

python 复制代码
async def main(args):
    return 2 + 3

✅ 同时 print + return

python 复制代码
async def main(args):
    print("hello")
    return {"sum": 2 + 3}

返回结构:

json 复制代码
{
  "stdout": "hello\n",
  "result": { "sum": 5 }
}

八、在 Python 中集成(推荐)

LangChain 官方提供了 Python 封装包:

8.1 安装

bash 复制代码
pip install langchain-sandbox

8.2 Python 示例

python 复制代码
from langchain_sandbox import PyodideSandbox
import asyncio

async def run():
    sandbox = PyodideSandbox(
        allow_net=False,
        allow_read=False,
        allow_write=False,
    )

    result = await sandbox.execute("""
async def main(args):
    print("hello from pyodide")
    return 1 + 2

await main({})
""")

    print("status:", result.status)
    print("stdout:", result.stdout)
    print("result:", result.result)

asyncio.run(run())

结果

bash 复制代码
status: success
stdout: hello from pyodide
result: 3

九、权限控制(安全关键)

参数 说明
allow_net 是否允许联网
allow_read 文件读取白名单
allow_write 文件写入
allow_env 读取环境变量
allow_run 执行子进程
memory_limit_mb 内存限制

示例:

python 复制代码
sandbox = PyodideSandbox(
    allow_net=False,
    allow_read=["data"],
    allow_write=False,
    memory_limit_mb=32,
)

十、典型应用场景

✔ LLM Agent 执行代码

✔ LangChain Tool Sandbox

✔ 在线 Python 解释器

✔ 插件系统

✔ 教育 / 判题系统


十一、常见问题

Q1:stdout 很乱正常吗?

✅ 正常

第一次会输出 Pyodide 包安装日志
生产环境请只信 result 字段


Q2:能安装 pandas / numpy 吗?

⚠️ 只能安装 pure Python / WASM 兼容包

❌ 不支持 CPython C 扩展(如 torch)


十二、官方资源汇总


十三、总结

jsr:@langchain/pyodide-sandbox 是目前 LLM 场景下最优雅的 Python 沙箱方案之一

轻量、安全、Agent 友好

非常适合用在:

  • AI Agent
  • 多租户执行
  • 自动化平台
相关推荐
喵手3 分钟前
Python爬虫实战:地图 POI + 行政区反查实战 - 商圈热力数据准备完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·地区poi·行政区反查·商圈热力数据采集
熊猫_豆豆9 分钟前
YOLOP车道检测
人工智能·python·算法
nimadan1210 分钟前
**热门短剧小说扫榜工具2025推荐,精准捕捉爆款趋势与流量
人工智能·python
wuli_滔滔10 分钟前
CANN安全机制源码探秘 仓库中的权限校验与数据加密实现
安全·cann
默默前行的虫虫14 分钟前
MQTT.fx实际操作
python
YMWM_24 分钟前
python3继承使用
开发语言·python
JMchen12325 分钟前
AI编程与软件工程的学科融合:构建新一代智能驱动开发方法学
驱动开发·python·软件工程·ai编程
liann1191 小时前
3.1_网络——基础
网络·安全·web安全·http·网络安全
亓才孓1 小时前
[Class类的应用]反射的理解
开发语言·python
独行soc1 小时前
2026年渗透测试面试题总结-17(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮