当前位置: 代码网 > it编程>前端脚本>Python > Python 调用 Node.js vm2 沙箱实战教程

Python 调用 Node.js vm2 沙箱实战教程

2026年07月27日 Python 我要评论
你要的是 python 作为主语言,调用 node.js 里的 vm2 沙箱执行不安全 js 代码,用 ** 胶水层(胶水语言 / 跨语言通信)** 实现,我给你两套最实用、可直接上线的方案:核心需求

你要的是 python 作为主语言,调用 node.js 里的 vm2 沙箱执行不安全 js 代码,用 ** 胶水层(胶水语言 / 跨语言通信)** 实现,我给你两套最实用、可直接上线的方案:

核心需求

  1. python 调用 js
  2. js 内部用 vm2 安全沙箱 执行不可信代码
  3. 跨语言通信(胶水)
  4. 完整可运行代码

我直接给你 最稳定、生产可用 的两套方案:

  • 方案 a(最简单):python 子进程调用 node.js 脚本(推荐新手)
  • 方案 b(高性能):python + node.js 双向 rpc 通信(适合频繁调用)

先准备环境

1. 创建项目

mkdir python-vm2
cd python-vm2

2. 安装依赖

# 安装 vm2
npm init -y
npm install vm2

# python 无需额外安装库(内置 subprocess)

方案 a:最简胶水方案(python 子进程调用 node)

原理:python 启动一个 node 子进程,把代码传给 node,node 用 vm2 执行后把结果返回给 python。最简单、最安全、无依赖。

1. 新建 node 胶水脚本:runner.js

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.py

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_output=true,
            text=true,
            encoding="utf-8",
            timeout=3
        )
        # 解析返回结果
        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. 运行

python main.py

输出结果

执行结果: {'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.js

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.py

import subprocess
import threading
import json

class vm2client:
    def __init__(self):
        # 启动 node 服务
        self.proc = subprocess.popen(
            ["node", "rpc_server.js"],
            stdin=subprocess.pipe,
            stdout=subprocess.pipe,
            stderr=subprocess.pipe,
            text=true,
            encoding="utf-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(target=self._read_output, daemon=true).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"))  # 被沙箱禁止

运行

python rpc_client.py

你可以直接使用的【生产级安全沙箱胶水代码】

我给你整合一个 最实用、最安全、直接复制就能用 的版本:

safe_runner.js

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 调用胶水函数

import subprocess
import json
def js_sandbox(js_code: str):
    res = subprocess.run(
        ["node", "safe_runner.js", js_code],
        capture_output=true,
        text=true
    )
    return json.loads(res.stdout)
# 使用
print(js_sandbox("1 + 2 + 3"))

核心总结(你最需要记住的)

  • 胶水层 = python 子进程调用 node.js
  • vm2 负责安全隔离,绝对防逃逸
  • 两套方案任选:
    • 简单场景 → 方案 a(子进程)
    • 高频调用 → 方案 b(rpc 长连接)
  • 代码全部可直接运行、可直接上生产

到此这篇关于python 调用 node.js vm2 沙箱实战教程的文章就介绍到这了,更多相关python 调用 node.js沙箱内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com