核心方法概览
-
使用
PyExecJS库 (最通用、最简单)
(图片来源网络,侵删)- 原理:
PyExecJS作为一个“胶水库”,它本身不执行 JS,而是通过调用你系统上已有的 JavaScript 运行时环境来执行代码。 - 优点:简单、跨平台、支持多种 JS 运行时(如 Node.js、PyV8、PhantomJS 等)。
- 缺点:性能不是最优,因为它需要启动一个外部进程或解释器来执行 JS 代码。
- 原理:
-
使用
node.js作为后端 (功能最强大、性能最好)- 原理:通过 Python 的
subprocess模块,调用node命令来执行一个.js文件,或者通过标准输入/输出来传递代码和获取结果。 - 优点:性能极高,可以访问 Node.js 生态系统中的所有库(如
crypto,axios等),功能最强大。 - 缺点:需要在系统上安装 Node.js,代码交互相对复杂一些。
- 原理:通过 Python 的
-
使用
PyV8(已过时,不推荐)- 原理:直接将 Google V8 JavaScript 引擎编译到 Python 中,提供一个高性能的 JS 执行环境。
- 优点:性能非常高,因为它直接集成在 Python 进程中,无需外部进程。
- 缺点:已停止维护多年,兼容性差,安装困难,不推荐在新项目中使用。
-
使用
Transcrypt或Pyodide(浏览器环境)- 原理:这些工具主要用于将 Python 代码编译成 JavaScript,以便在浏览器中运行,它们也可以用来在 Python 环境中模拟浏览器环境并执行 JS。
- 适用场景:当你需要模拟浏览器环境,执行依赖 DOM API 的 JS 代码时(模拟用户交互)。
- 缺点:配置复杂,性能开销大,主要用于 WebAssembly 相关的开发。
使用 PyExecJS (推荐入门)
这是最简单直接的方法,适合大多数不需要极致性能的场景。

安装
你需要安装 PyExecJS 库:
pip install PyExecJS
你需要安装一个 JavaScript 运行时。Node.js 是最流行和推荐的选择。
- 安装 Node.js: 访问 Node.js 官网 下载并安装。
- 验证安装: 安装完成后,在终端运行
node -v和npm -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 对象之间的转换。

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 的方案,这两种方法是目前社区最主流、最稳定的解决方案。
