为什么需要 Python 中的 JavaScript 引擎?
想象一下以下常见场景:

- 前端自动化测试:你的后端服务是用 Python (Django/Flask) 编写的,但你需要运行使用 Cypress、Playwright 或 Puppeteer 等工具编写的端到端 (E2E) 测试,这些工具本质上是 Node.js 应用,但你可以通过 Python 脚本来触发和管理它们。
- 执行前端代码:你有一个由 JavaScript 生成或处理的数据(一个复杂的可视化图表配置),你想在 Python 后端执行这段 JS 代码来生成最终的 HTML 或数据,而无需启动一个完整的 Node.js 环境。
- 利用现有的 JS 库:某个强大的库只有 JavaScript 版本(一些图像处理、科学计算或特定的 Web API 库),你可以通过 Python 来调用它,而不是用 Python 重新实现一遍。
- 服务器端渲染 (SSR):在 Python Web 框架中,集成一个 React 或 Vue 应用,在服务器端渲染页面,然后将 HTML 发送给客户端。
为了实现这些,我们需要一个在 Python 中运行 JavaScript 代码的“桥梁”,这个桥梁就是 JavaScript 引擎。
主流 Python JavaScript 引擎推荐
有几个非常优秀的库可以让你在 Python 中运行 JavaScript,它们各有侧重,适用于不同的场景。
PyMiniRacer (推荐用于高性能场景)
PyMiniRacer 是一个高性能的 JavaScript 引擎,它将 Google 的 V8 引擎(也就是 Chrome 和 Node.js 使用的核心)编译成一个 Python 扩展。
- 核心:Google V8
- 优点:
- 性能极高:因为它直接使用了 V8,所以执行 JS 代码的速度非常快,接近原生 Node.js。
- 内存效率高:V8 引擎被编译成一个单独的库,与 Python 进程共享内存,开销相对较小。
- 功能完整:支持最新的 ECMAScript (JavaScript) 标准。
- 缺点:
- 安装复杂:需要编译 C++ 扩展,在某些系统(特别是 Windows 或没有编译工具链的 Linux 环境)上安装可能会遇到困难。
- 不是纯 Python:它是一个 C 扩展,依赖于系统环境。
- 适用场景:
- 需要在 Python 中大量、频繁地执行 JS 代码。
- 对性能要求苛刻的场景,例如处理复杂的 JS 算法或数据转换。
安装:

# 可能需要先安装 build-essential (Debian/Ubuntu) 或 Xcode Command Line Tools (macOS) pip install py_mini_racer
示例代码:
from py_mini_racer import JSException, MiniRacer
# 创建一个 JS 运行时环境
ctx = MiniRacer()
# 执行简单的 JS 代码
print(ctx.execute("1 + 2")) # 输出: 3
# 调用 JS 函数
js_code = """
(function add(a, b) {
return a + b;
})
"""
ctx.eval(js_code)
print(ctx.call("add", 10, 20)) # 输出: 30
# 在 JS 和 Python 之间传递复杂数据(JSON 格式)
data = {"name": "Alice", "age": 30, "skills": ["Python", "JS"]}
# 将 Python 字典转为 JSON 字符串传给 JS
json_data = ctx.execute(f"JSON.stringify({data})")
print(json_data) # 输出: {"name":"Alice","age":30,"skills":["Python","JS"]}
# 从 JS 接收数据并转为 Python 字典
js_result = ctx.execute("JSON.parse('{\"city\": \"New York\"}')")
print(js_result) # 输出: {'city': 'New York'}
print(type(js_result)) # 输出: <class 'dict'>
PyExecJS (通用型,易于使用)
PyExecJS 是一个更通用的库,它不直接包含 JS 引擎,而是作为适配器,让你可以方便地在多种不同的 JS 运行时之间切换。
- 核心:适配器模式,支持 Node.js, PyV8, PhantomJS, JavaScriptCore 等。
- 优点:
- 安装极其简单:
pip install PyExecJS,无需编译。 - 通用性强:如果系统已经安装了 Node.js,它会自动使用它,非常方便。
- 跨平台性好:只要有可用的后端 JS 环境,就能运行。
- 安装极其简单:
- 缺点:
- 性能依赖于后端:如果使用 Node.js 作为后端,性能不错,但启动一个新的 Node.js 进程会有一定的开销,不适合高频调用。
- 不是引擎本身:它是一个“指挥官”,性能上限取决于它指挥的“士兵”(哪个 JS 引擎)。
- 适用场景:
- 快速原型开发。
- 系统已经安装了 Node.js,希望简单地在 Python 中调用 JS。
- 不关心底层引擎,只希望代码能运行起来。
安装:
pip install PyExecJS
示例代码:

import execjs
# PyExecJS 会自动在系统中寻找可用的 JS 运行时
# 如果你安装了 Node.js,它会默认使用它
# 执行 JS 代码
ctx = execjs.compile("""
function add(a, b) {
return a + b;
}
function greet(name) {
return 'Hello, ' + name + '!';
}
""")
# 调用函数
print(ctx.call("add", 5, 7)) # 输出: 12
print(ctx.call("greet", "World")) # 输出: Hello, World!
Transcrypt (将 Python 代码编译成 JavaScript)
Transcrypt 的思路与前两者完全不同,它不是一个在 Python 中“运行”JS 的引擎,而是一个编译器,它允许你使用 Python 的语法和库来编写代码,然后将其编译成能在浏览器或 Node.js 中运行的 JavaScript。
- 核心:Python 到 JavaScript 的编译器。
- 优点:
- 语言统一:你可以用 Python 的思维和生态(部分库)来开发前端代码。
- 类型检查:编译时可以发现一些错误。
- 代码复用:理论上,一些核心业务逻辑可以在 Python 后端和 JavaScript 前端之间共享。
- 缺点:
- 不是运行时:它不能让你在 Python 脚本中动态执行一段 JS 字符串。
- 不是 100% Python:不是所有的 Python 库和语法都能被支持,你需要使用 Transcrypt 兼容的子集。
- 学习成本:你需要理解它的工作方式和限制。
- 适用场景:
- 想用 Python 语言开发纯前端应用(WebAssembly 的一个替代方案)。
- 希望在前后端共享大量 Python 代码逻辑。
安装与使用:
pip install transcrypt # 创建一个 Python 模块,mymodule.py # transcrypt -b -k mymodule # 这会生成 JS 文件,可以在浏览器中运行
| 特性 | PyMiniRacer | PyExecJS | Transcrypt |
|---|---|---|---|
| 核心思想 | 在 Python 中嵌入 V8 引擎 | Python 调用外部 JS 运行时的适配器 | 将 Python 代码编译成 JS |
| 性能 | 非常高 (接近原生) | 中等 (依赖后端,如 Node.js) | 编译后性能好,但非运行时性能 |
| 安装难度 | 较高 (需编译) | 非常简单 | 简单 |
| 跨平台性 | 一般 (依赖编译环境) | 非常好 (只要有后端引擎) | 好 |
| 主要用途 | 高性能 JS 代码执行 | 通用 JS 代码调用、快速原型 | 用 Python 编写前端/JS 代码 |
| 与 Python 交互 | 直接传递 Python 对象 | 通过 JSON 字符串交互 | 编译时确定,无运行时交互 |
如何选择?
- 追求极致性能,且不介意安装的复杂性:选择 PyMiniRacer,它是目前 Python 执行 JS 代码性能的标杆。
- 快速验证想法、系统已有 Node.js、或希望安装过程丝滑无阻:选择 PyExecJS,它是最简单、最通用的选择。
- 想用 Python 语言为浏览器或 Node.js 编写代码,实现前后端语言统一:选择 Transcrypt,它是一个编译工具,而不是运行
