杰瑞科技汇

Python 如何直接执行 JavaScript 代码?

核心方法概览

  1. 使用 PyExecJS 库 (最通用、最简单)

    Python 如何直接执行 JavaScript 代码?-图1
    (图片来源网络,侵删)
    • 原理PyExecJS 作为一个“胶水库”,它本身不执行 JS,而是通过调用你系统上已有的 JavaScript 运行时环境来执行代码。
    • 优点:简单、跨平台、支持多种 JS 运行时(如 Node.js、PyV8、PhantomJS 等)。
    • 缺点:性能不是最优,因为它需要启动一个外部进程或解释器来执行 JS 代码。
  2. 使用 node.js 作为后端 (功能最强大、性能最好)

    • 原理:通过 Python 的 subprocess 模块,调用 node 命令来执行一个 .js 文件,或者通过标准输入/输出来传递代码和获取结果。
    • 优点:性能极高,可以访问 Node.js 生态系统中的所有库(如 crypto, axios 等),功能最强大。
    • 缺点:需要在系统上安装 Node.js,代码交互相对复杂一些。
  3. 使用 PyV8 (已过时,不推荐)

    • 原理:直接将 Google V8 JavaScript 引擎编译到 Python 中,提供一个高性能的 JS 执行环境。
    • 优点:性能非常高,因为它直接集成在 Python 进程中,无需外部进程。
    • 缺点已停止维护多年,兼容性差,安装困难,不推荐在新项目中使用。
  4. 使用 TranscryptPyodide (浏览器环境)

    • 原理:这些工具主要用于将 Python 代码编译成 JavaScript,以便在浏览器中运行,它们也可以用来在 Python 环境中模拟浏览器环境并执行 JS。
    • 适用场景:当你需要模拟浏览器环境,执行依赖 DOM API 的 JS 代码时(模拟用户交互)。
    • 缺点:配置复杂,性能开销大,主要用于 WebAssembly 相关的开发。

使用 PyExecJS (推荐入门)

这是最简单直接的方法,适合大多数不需要极致性能的场景。

Python 如何直接执行 JavaScript 代码?-图2
(图片来源网络,侵删)

安装

你需要安装 PyExecJS 库:

pip install PyExecJS

你需要安装一个 JavaScript 运行时。Node.js 是最流行和推荐的选择。

  • 安装 Node.js: 访问 Node.js 官网 下载并安装。
  • 验证安装: 安装完成后,在终端运行 node -vnpm -v,如果能显示版本号,说明安装成功。

PyExecJS 会自动检测到系统中安装的 Node.js。

基本使用

import execjs
# 1. 直接执行一段 JS 代码
js_code = """
function add(a, b) {
    return a + b;
}
"""
# 创建一个 JS 运行时上下文
ctx = execjs.compile(js_code)
# 调用 JS 函数
result = ctx.call("add", 10, 20)
print(f"10 + 20 = {result}")  # 输出: 10 + 20 = 30
# 2. 执行一个 JS 文件
# 假设你有一个名为 utils.js 的文件
# utils.js 内容:
// function greet(name) {
//     return "Hello, " + name + "!";
// }
// module.exports = { greet: greet };
# 在 Python 中调用
with open('utils.js', 'r', encoding='utf-8') as f:
    file_js_code = f.read()
ctx_file = execjs.compile(file_js_code)
greeting = ctx_file.call('greet', 'Python')
print(greeting) # 输出: Hello, Python!

传递和接收复杂数据类型

PyExecJS 可以自动处理 Python 字典和 JavaScript 对象之间的转换。

Python 如何直接执行 JavaScript 代码?-图3
(图片来源网络,侵删)
import execjs
js_code = """
function process_data(data) {
    // JS 可以直接操作 Python 传入的字典
    data.age = data.age + 1;
    data.is_processed = true;
    return data;
}
"""
ctx = execjs.compile(js_code)
# Python 字典
python_data = {
    "name": "Alice",
    "age": 30,
    "city": "New York"
}
# 调用函数,并传入字典
processed_data = ctx.call("process_data", python_data)
# 返回的也是一个 Python 字典
print(processed_data)
# 输出: {'name': 'Alice', 'age': 31, 'city': 'New York', 'is_processed': True}

使用 node.js 作为后端 (推荐高性能)

当你的 JS 代码很复杂,或者需要调用 Node.js 特有的模块时,这种方法是最佳选择。

准备工作

确保你的系统已经安装了 Node.js。

创建一个 JavaScript 文件

创建一个名为 calculate.js 的文件,它将从命令行参数接收输入,并将结果输出到标准输出。

calculate.js:

// 从命令行参数获取输入
const args = process.argv.slice(2); // 前两个参数是 node 和文件名
// 第一个参数是函数名,其余是参数
const functionName = args[0];
const params = args.slice(1);
// 一个简单的函数库
const functions = {
    sum: (...numbers) => numbers.reduce((a, b) => a + b, 0),
    greet: (name) => `Hello, ${name} from Node.js!`
};
// 执行函数并打印结果
if (functions[functionName]) {
    const result = functions[functionName](...params);
    console.log(JSON.stringify(result)); // 使用 JSON.stringify 确保数据格式正确
} else {
    console.log(JSON.stringify({ error: "Function not found" }));
}

在 Python 中调用

使用 Python 内置的 subprocess 模块来执行 node 命令。

import subprocess
import json
def run_node_script(function_name, *args):
    """
    执行 Node.js 脚本并返回结果
    """
    try:
        # 构建命令
        # ['node', 'calculate.js', 'sum', 10, 20, 30]
        command = ['node', 'calculate.js', function_name] + [str(arg) for arg in args]
        # 执行命令并捕获输出
        # text=True 会自动解码输出为字符串
        # check=True 会在命令失败时抛出 CalledProcessError
        result = subprocess.run(command, capture_output=True, text=True, check=True)
        # 解析 JSON 输出
        return json.loads(result.stdout)
    except subprocess.CalledProcessError as e:
        print(f"Error executing Node.js script: {e}")
        print(f"Stderr: {e.stderr}")
        return None
    except json.JSONDecodeError:
        print("Failed to decode JSON from Node.js output")
        return None
# --- 使用示例 ---
# 1. 调用 sum 函数
result_sum = run_node_script('sum', 10, 20, 30)
print(f"Sum result: {result_sum}") # 输出: Sum result: 60
# 2. 调用 greet 函数
result_greet = run_node_script('greet', 'Bob')
print(f"Greet result: {result_greet}") # 输出: Greet result: Hello, Bob from Node.js!
# 3. 调用一个不存在的函数
result_error = run_node_script('nonexistent_func')
print(f"Error result: {result_error}") # 输出: Error result: {'error': 'Function not found'}

优点

  • 高性能:Node.js 的 V8 引擎非常快。
  • 功能强大:可以轻松使用任何 npm 包,只需在 JS 文件中 require 即可。
  • 解耦:Python 和 JS 代码分离,结构清晰。

如何选择?

场景 推荐方法 理由
快速原型、简单脚本、偶尔执行 JS PyExecJS 安装配置简单,几行代码就能搞定,足够满足需求。
需要处理大量 JS 逻辑、性能敏感 node.js + subprocess 性能最佳,能利用整个 Node.js 生态,适合生产环境。
需要模拟浏览器环境、操作 DOM Pyodide / Playwright Pyodide 在浏览器中运行 JS,Playwright 可以控制真实浏览器,适合爬虫和自动化测试。
旧项目维护 PyV8 不推荐,仅作为了解,新项目请避免。

对于绝大多数开发者来说,PyExecJS 是入门和日常使用的最佳选择,它简单、灵活,当你发现性能成为瓶颈,或者需要使用 Node.js 特有模块时,再转向 node.js + subprocess 的方案,这两种方法是目前社区最主流、最稳定的解决方案。

分享:
扫描分享到社交APP
上一篇
下一篇