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

 更新时间:2026年07月27日 10:13:43   作者:ZHANG13HAO  
本文提供了两种Python调用Node.js vm2沙箱执行不安全JS代码的实用方案,方案A采用子进程方式,方案B采用RPC长连接方式,适合高频调用场景,下面可以了解一下

你要的是 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沙箱内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • PyQt5每天必学之布局管理

    PyQt5每天必学之布局管理

    这篇文章主要为大家详细介绍了PyQt5每天必学之布局管理的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • python如何求圆的面积

    python如何求圆的面积

    在本篇文章里小编给大家分享了关于python求圆面积的实例代码及相关扩展内容,需要的朋友们可以学习下。
    2020-07-07
  • Tkinter 组件Scrollbar的具体使用

    Tkinter 组件Scrollbar的具体使用

    本文主要介绍了Tkinter 组件Scrollbar的具体使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • 使用Keras建立模型并训练等一系列操作方式

    使用Keras建立模型并训练等一系列操作方式

    这篇文章主要介绍了使用Keras建立模型并训练等一系列操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • python爬虫增加访问量的方法

    python爬虫增加访问量的方法

    这篇文章主要介绍了python爬虫增加访问量的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • python实现单张图像拼接与批量图片拼接

    python实现单张图像拼接与批量图片拼接

    这篇文章主要为大家详细介绍了python实现单张图像拼接与批量图片拼接,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • django使用channels实现通信的示例

    django使用channels实现通信的示例

    这篇文章主要介绍了django使用channels实现通信的示例,帮助大家更好的理解和学习django框架,感兴趣的朋友可以了解下
    2020-10-10
  • 如何让python程序正确高效地并发

    如何让python程序正确高效地并发

    这篇文章主要介绍了如何让python程序正确高效地并发,文章围绕主题的相关资料展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-06-06
  • 保姆级官方yolov7训练自己的数据集及项目部署详解

    保姆级官方yolov7训练自己的数据集及项目部署详解

    最近使用了YOLOv7训练自己的数据集,接下来简单记录一下项目的部署,这篇文章主要给大家介绍了关于保姆级官方yolov7训练自己的数据集及项目部署的相关资料,需要的朋友可以参考下
    2022-08-08
  • Django使用rest_framework写出API

    Django使用rest_framework写出API

    这篇文章主要介绍了Django使用rest_framework写出API,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05

最新评论