21CTO导读:PythonMonkey 是一种嵌入在Python中的创新JavaScript运行时,它的目标是“弥合”世界上两种最流行的编程语言之间的差距。
PythonMonkey 是 Python 内部的 JavaScript 运行时,基于Mozilla的SpiderMonkey引擎构建。开发者可以将其用作 Python 库,在 Python 中运行 JavaScript 代码。
网址:https://spidermonkey.dev/
图 1 SpiderMonkey的网站截图
Distributive是一家位于加拿大安大略省金斯顿的云计算初创公司,这家公司构建了 PythonMonkey,其目标是可以将其 JavaScript NodeJS SDK 直接移植到 Python,而不需要再维护两个项目,从而将代码维护成本降低了一半。
Distributive 的开发者 Will Pringle 表示:“我们希望 PythonMonkey 能够帮助缩小数百万 npm 包与 Python 开发者之间的差距,并有朝一日能够成为一个独立的 JavaScript 运行时,与Node.js、Bun和Deno竞争 ,但能够使用 JS 中的‘任何’Python 包。”
Pringle 在介绍该技术的博客文章中写道:“从实际情况中,PythonMonkey 使开发者能够轻松地在 JavaScript 中使用 Python 代码,并且几乎没有性能损失。”
请大家留意,Distributive 计划下个月发布 PythonMonkey 1.0。
WebAssembly API 和引擎
Pringle 在文章中这样说道:
“例如,可以从 JavaScript 库中 调用NumPy之类的 Python 包,或者直接从 Python使用crypto-js之类的 NPM 包。此外使用 SpiderMonkey 的 WebAssembly API 和引擎,在 Python 中执行WebAssembly模块将变得非常简单。”
该库利用了 SpiderMonkey 的功能,包括 WebAssembly 引擎,允许 Python 在沙箱中运行来自多种语言(如 C、C++、Rust等)的不受信任的 WASM 代码。
此外,开发者可以使用 PythonMonkey 重构用 Python 编写的缓慢“热循环”,以便在 JavaScript 中执行,利用 SpiderMonkey 的即时编译器获得接近本机代码的速度。
PMJS
此外,PythonMonkey 还附带 PMJS,这是一个类似 Node.js 的 JavaScript 运行环境,支持从 JavaScript 调用 Python 库。
简单代码示例
Pringle 在他的文章中提供了一些编码指导,包括下面的“hello world”示例。以下的代码示例演示了如何将 JavaScript 生成的字符串并返回到 Python 上下文。
请看如下代码:
>>> import pythonmonkey as pm
>>> hello = pm.eval(” ‘Hello World’.toUpperCase(); “)
>>> print(hello)
‘HELLO WORLD’
下面是个更复杂的例子演示了将 Python 打印函数作为参数传递给 JavaScript 函数,然后从 Python 中调用该 JavaScript 函数。
请看如下代码:
>>> import pythonmonkey as pm>>> hello = pm.eval(“(func) => { func(‘Hello World!’)}”)
>>> hello(print)
Hello World!
本代码示例使用 pmjs 执行一个使用 Python 之print 函数的 JavaScript 文件。可以使用执行:
pmjs main.js
main.js
const pyPrint = python.eval(“print”);
pyPrint(“Hello, World!”); // 输出“Hello, World!”
项目的目标
该项目的目标如下:
-
速度快并节省内存。
-
开发者可自定义优先使用 JS 或 Python 编写代码。
-
从 Python中调用JavaScript。
-
从 JavaScript 使用 Python 库。
-
同一进程运行 JavaScript 与 Python 虚拟机——无需序列化、管道等。
-
Python 列表和字典的行为类似于 JavaScript 数组和对象,反之亦然,完全适应给定的上下文。
PythonMonkey 的起源
Distributive 的首席技术官Wes Garland创建了 PythonMonkey,以便让本公司的开发人员工作更加轻松。
Garland 在 2007 年左右创建了 Node.js 的前身 gpsee ,有点今天像 PythonMonkey 一样基于 Mozilla 的 SpiderMonkey 引擎构建。
Pringle 这样说道:
“我们在 Distributive 有一个庞大而复杂的客户端 SDK,名为 dcp-client,是用 JavaScript 编写的。里面有很多业务逻辑,因此我们不想用 Python 重写它,也不想同时维护两个项目——这实际上会使我们在 SDK 上的开发成本翻倍。PythonMonkey 使我们能够将所有底层逻辑从 JavaScript 库移植到 Python,同时只维护一个代码库。”
只是一个主 JavaScript 商店
由于公司的产品需要在 Web 堆栈中运营,因此 Distributive 主要使用 JavaScript 进行开发。
Pringle 表示:“我们正在构建DCP(分布式计算协议),这是一个计算市场,人们可以从其他人的家用电脑上租用 CPU/GPU 周期。我们的想法是,如果你有一台闲置的电脑,你可以将它连接到我们的云计算网络,通过计算其他人的工作负载来赚钱。将你的电脑变成工作节点的程序是一个 JavaScript 引擎,它可以执行 JS 程序、WebAssembly 或任何可以编译为(或有解释器编译为)WebAssembly 的编程语言。
“您也可以直接在浏览器中运行它。无论如何,我们的实现中有很多 JavaScript 代码,但每个人都想用 Python 编写这类东西,因此 PythonMonkey 使 Python 开发人员能够使用我们的产品 (DCP) — 而无需我们重新编写我们的 SDK。”
Pringle 目前正在开发 Distributive 的 Python SDK,该公司预计将在未来几周内发布它。
项目的发展
自去年 7 月推出 PythonMonkey 以来,Distributive 对该技术进行了大量改进,包括:
Web 堆栈 API
-
XMLHttpRequest 从头开始实现API — —使流行的 JavaScript 库(如 socketio)能够使用标准 JavaScript 网络 API 在 PythonMonkey 中运行。
-
实现了几个计时器全局函数:setInterval / clearInterval, setImmediate / clearImmediate 和 setTimeout / clearTimeout ,返回带有和方法的 Node.js 风格的Timeout类。.ref().unref()
-
实现了 API 中所有缺失的方法console,现在其行为与 Web 规范https://console.spec.whatwg.org/console相同。
-
atob,btoa功能。
跨语言强制转换
-
用户现在可以用 JavaScript 包装/代理任意 Python 对象。
-
更好的跨语言迭代器支持。
异常处理
-
实现了完整的跨语言堆栈跟踪。
-
改进了跨语言嵌套异常处理和承诺拒绝处理。
-
未捕获异常处理程序
JavaScript 引擎更新
-
将 SpiderMonkey 更新到最新版本,让用户可以享受与最新 Firefox 相同的新 JS + WASM 语言功能,并且性能更佳。
-
向 SpiderMonkey贡献了一个补丁来修复一个错误。
开发者体验提升
-
pmdb使用名为(受启发gdb)和 WTFPythonMonkey(受wtfnode启发)的嵌入式调试器工具获得更好的开发人员体验。
-
为开发人员提供更好的 Python 类型提示和文档。
-
用户现在可以用 JavaScript 包装/代理任意 Python 对象。
-
更好的跨语言迭代器支持。
异常处理
-
实现了完整的跨语言堆栈跟踪。
-
改进了跨语言嵌套异常处理和承诺拒绝处理。
-
未捕获异常处理程序
JavaScript 引擎更新
-
将 SpiderMonkey 更新到最新版本,让用户可以享受与最新 Firefox 相同的新 JS + WASM 语言功能,并且性能更佳。
-
向 SpiderMonkey贡献了一个补丁来修复一个错误。
开发者体验提升
-
pmdb使用名为(受启发gdb)和 WTFPythonMonkey(受wtfnode启发)的嵌入式调试器工具获得更好的开发人员体验。
-
为开发人员提供更好的 Python 类型提示和文档。
-
实现了完整的跨语言堆栈跟踪。
-
改进了跨语言嵌套异常处理和承诺拒绝处理。
-
未捕获异常处理程序
JavaScript 引擎更新
-
将 SpiderMonkey 更新到最新版本,让用户可以享受与最新 Firefox 相同的新 JS + WASM 语言功能,并且性能更佳。
-
向 SpiderMonkey贡献了一个补丁来修复一个错误。
开发者体验提升
-
pmdb使用名为(受启发gdb)和 WTFPythonMonkey(受wtfnode启发)的嵌入式调试器工具获得更好的开发人员体验。
-
为开发人员提供更好的 Python 类型提示和文档。
-
将 SpiderMonkey 更新到最新版本,让用户可以享受与最新 Firefox 相同的新 JS + WASM 语言功能,并且性能更佳。
-
向 SpiderMonkey贡献了一个补丁来修复一个错误。
开发者体验提升
-
pmdb使用名为(受启发gdb)和 WTFPythonMonkey(受wtfnode启发)的嵌入式调试器工具获得更好的开发人员体验。
-
为开发人员提供更好的 Python 类型提示和文档。
-
pmdb使用名为(受启发gdb)和 WTFPythonMonkey(受wtfnode启发)的嵌入式调试器工具获得更好的开发人员体验。
-
为开发人员提供更好的 Python 类型提示和文档。
模块系统
PythonMonkey 的模块系统允许轻松将 JavaScript 库移植到 Python ,反之亦然。Pringle 写道,运行时使开发人员“能够轻松地将他们的 JavaScript 库移植到 Python,而无需承受用 Python 重写库和维护移植的昂贵负担”。
此外,“JavaScript 也非常适合高度异步的工作负载,而 Python 则不然,”Pringle 在他的帖子中解释道。“在 Distributive,我们打算使用这个库来执行我们复杂的 dcp-client 库,该库是用 JS 编写的,并支持在 Web 堆栈上进行分布式计算。”
同时,Pringle 指出,PythonMonkey 的目标是通过尽可能共享不可变的备用存储来最大限度地减少内存消耗和复制开销。
PythonMonkey 路线图
Pringle 在去年发布时写道:“PythonMonkey 的路线图包括许多功能与新改进,以扩展其可用性,例如使用 esm 语法在 JavaScript 中导入 Python 模块、XMLHttpRequest、实现不依赖 Python 的独立事件循环,以及支持 Node.js API(例如 fs、path、process),这将允许 Python 使用 express.js 和 socket.io等 NPM 包。”
该公司已经实现了很多目标。
路线图上提出的另一个目标是将 PMJS 扩展为完全集成的 Node.js 环境,该环境可以作为 Node.js 的替代品,并且还能够从 JavaScript 使用 Python 包。
通过这些计划中的增强功能,PythonMonkey 和 PMJS 旨在为开发人员提供完全集成的 Python-JS 环境。
同时,Pringle 将 PythonMonkey 与JS2PY、PyV8和Metacall等相关项目进行了比较,突出了 PythonMonkey 在性能和功能方面的优势。
还有比相关项目更优秀的吗?
作者:场长
说明:各位可以在Google Colab上试用 PythonMonkey 。
https://colab.research.google.com/drive/1INshyn0gNMgULQVtXlQWK1QuDGwdgSGZ?usp=sharing