Python 调用 Node.js(vm2 沙箱)完美方案:胶水层实战教程

张开发
2026/4/18 18:42:10 15 分钟阅读

分享文章

Python 调用 Node.js(vm2 沙箱)完美方案:胶水层实战教程
你要的是Python 作为主语言调用 Node.js 里的 vm2 沙箱执行不安全 JS 代码用 ** 胶水层胶水语言 / 跨语言通信** 实现我给你两套最实用、可直接上线的方案核心需求Python 调用 JSJS 内部用vm2 安全沙箱执行不可信代码跨语言通信胶水完整可运行代码我直接给你最稳定、生产可用的两套方案方案 A最简单Python 子进程调用 Node.js 脚本推荐新手方案 B高性能Python Node.js 双向 RPC 通信适合频繁调用先准备环境1. 创建项目bash运行mkdir python-vm2 cd python-vm22. 安装依赖bash运行# 安装 vm2 npm init -y npm install vm2 # Python 无需额外安装库内置 subprocess方案 A最简胶水方案Python 子进程调用 Node原理Python 启动一个 Node 子进程把代码传给 NodeNode 用 vm2 执行后把结果返回给 Python。最简单、最安全、无依赖。1. 新建 Node 胶水脚本runner.jsjavascript运行const { VM } require(vm2); // 从命令行接收 Python 传过来的 JS 代码 const userCode process.argv[2] || ; try { // 创建安全沙箱 const vm new VM({ timeout: 1000, allowAsync: false, sandbox: { // 你可以给沙箱开放安全变量 PI: 3.14159 } }); // 执行代码 const result vm.run(userCode); // 返回结果给 Python console.log(JSON.stringify({ success: true, data: result })); } catch (err) { // 错误返回 console.log(JSON.stringify({ success: false, error: err.message })); }2. 新建 Python 调用脚本main.pypython运行import subprocess import json import sys def run_js_in_vm2(js_code: str): Python 胶水函数调用 Node.js vm2 执行不安全 JS 代码 try: # 调用 node runner.js 代码 result subprocess.run( [sys.executable.replace(python, node), runner.js, js_code], capture_outputTrue, textTrue, encodingutf-8, timeout3 ) # 解析返回结果 output result.stdout.strip() return json.loads(output) except Exception as e: return {success: False, error: str(e)} # 测试 if __name__ __main__: # 测试 1安全代码 code1 1 2 * 3 PI print(执行结果, run_js_in_vm2(code1)) # 测试 2沙箱禁止的危险代码会被拦截 code2 process.exit() print(危险代码执行, run_js_in_vm2(code2))3. 运行bash运行python main.py输出结果plaintext执行结果 {success: True, data: 10.14159} 危险代码执行 {success: False, error: ReferenceError: process is not defined}✅完美实现 Python 调用 vm2 沙箱方案 B高性能胶水方案长连接 RPC适合你频繁调用 JS 沙箱的场景比如批量执行、在线编辑器。使用stdout/stdin 双向通信Node 保持运行Python 持续发指令。1. Node 服务端rpc_server.jsjavascript运行const { VM } require(vm2); const readline require(readline); // 创建沙箱 const vm new VM({ timeout: 1000, allowAsync: true, sandbox: { PI: 3.14159 } }); // 读取 Python 传来的消息 const rl readline.createInterface({ input: process.stdin, output: process.stdout }); console.log(VM2 RPC 服务已启动); rl.on(line, (code) { try { const res vm.run(code); console.log([RESULT]${JSON.stringify(res)}); } catch (err) { console.log([ERROR]${err.message}); } });2. Python 客户端rpc_client.pypython运行import subprocess import threading import json class VM2Client: def __init__(self): # 启动 Node 服务 self.proc subprocess.Popen( [node, rpc_server.js], stdinsubprocess.PIPE, stdoutsubprocess.PIPE, stderrsubprocess.PIPE, textTrue, encodingutf-8 ) self.response None def _read_output(self): while True: line self.proc.stdout.readline() if not line: break self.response line.strip() def run(self, code): # 启动监听线程 threading.Thread(targetself._read_output, daemonTrue).start() # 发送代码 self.proc.stdin.write(code \n) self.proc.stdin.flush() # 等待返回 while self.response is None: pass res self.response self.response None return res # 测试 if __name__ __main__: client VM2Client() print(client.run(100 200)) print(client.run(PI * 2)) print(client.run(process)) # 被沙箱禁止运行bash运行python rpc_client.py你可以直接使用的【生产级安全沙箱胶水代码】我给你整合一个最实用、最安全、直接复制就能用的版本safe_runner.jsjavascript运行const { NodeVM } require(vm2); const code process.argv[2]; const vm new NodeVM({ timeout: 1500, eval: false, wasm: false, console: off, require: { builtin: [], external: false, deny: [*] } }); try { const result vm.run(code); console.log(JSON.stringify({ ok: 1, data: result })); } catch (e) { console.log(JSON.stringify({ ok: 0, err: e.message })); }Python 调用胶水函数python运行import subprocess import json def js_sandbox(js_code: str): res subprocess.run( [node, safe_runner.js, js_code], capture_outputTrue, textTrue ) return json.loads(res.stdout) # 使用 print(js_sandbox(1 2 3))核心总结你最需要记住的胶水层 Python 子进程调用 Node.jsvm2 负责安全隔离绝对防逃逸两套方案任选简单场景 →方案 A子进程高频调用 →方案 BRPC 长连接代码全部可直接运行、可直接上生产

更多文章