Python 和 JavaScript 终于联姻了!PythonMonkey 要火?

家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。

什么是 PythonMonkey

A Mozilla SpiderMonkey JavaScript engine embedded into the Python VM, using the Python engine to provide the JS host environment.

PythonMonkey 是嵌入到 Python 运行时的 Mozilla SpiderMonkey JavaScript 引擎,使用 Python 引擎提供 Javascript 宿主环境。

其使用 cPython C API 在 Python 列表和字典上实现 JavaScript 数组和对象方法,并使用 Mozilla Firefox Spidermonkey JavaScript C++ API 实现相反的方法。

截至 2024 年 3 月,PythonMonkey 大约 95% 已达到 MVP,同时 Distributive 正在积极开发该产品。PythonMonkey 的目标是:

  • 快速且节省内存
  • 让使用 JS 或 Python 编写代码成为开发人员的偏好
  • 提供 Python 库 和 JavaScript 库的互操作性
  • 同一进程运行 JavaScript 和 Python VirtualMachines ,无需序列化、管道等
  • Python 列表和字典行为与 Javacript 数组和对象相同,反之亦然,完全适应给定上下文

目前 PythonMonkey 在 Github 通过 MIT 协议开源,是一个值得关注的开源项目。

如何使用 PythonMonkey

首先通过 PIP 安装包:

pip3 install pythonmonkey

下面示例返回一个 Python 函数,该函数使用 JS new 运算符调用函数:

import pythonmonkey as pm

>>> pm.eval("class MyClass { constructor() { console.log('ran ctor') }}")
>>> MyClass = pm.eval("MyClass")
>>> MyClass()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
pythonmonkey.SpiderMonkeyError: TypeError: class constructors must be invoked with 'new'

>>> MyClassCtor = pm.new(MyClass)
>>> MyClassCtor()
ran ctor
{}
>>>

PythonMonkey 目前已经支持所有 JS 标准类(数组、函数、对象、日期等)和对象(globalThis、FinalizationRegistry等),都可以作为 pythonmonkey 模块的导出,其是通过枚举当前 SpiderMonkey 上下文中的全局变量来生成的。 当前的列表是:

undefined, Boolean, JSON, Date, Math, Number, String, RegExp, Error, InternalError, AggregateError, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, ArrayBuffer, Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, Uint8ClampedArray, BigInt64Array, BigUint64Array, BigInt, Proxy, WeakMap, Map, Set, DataView, Symbol, Intl, Reflect, WeakSet, Promise, WebAssembly, WeakRef, Iterator, AsyncIterator, NaN, Infinity, isNaN, isFinite, parseFloat, parseInt, escape, unescape, decodeURI, encodeURI, decodeURIComponent, encodeURIComponent, Function, Object, debuggerGlobal, FinalizationRegistry, Array, globalThis


如果需要运行事件循环可以使用 setTimeout 和 Promise<=>awaitable:

import asyncio

async def async_fn():
  await pm.eval("""
    new Promise((resolve) => setTimeout((...args) => {
        console.log(args);
        resolve();
      }, 1000, 42, "abc")
    )
  """)
  await pm.eval("async (x) => await x")(asyncio.sleep(0.5))
asyncio.run(async_fn())

更多关于 PythonMonkey 的用法和特性可以参考文末资料,本文不再过多展开。

参考资料

https://github.com/Distributive-Network/PythonMonkey

https://medium.com/@willkantorpringle/pythonmonkey-javascript-wasm-interop-in-python-using-spidermonkey-bindings-4a8efce2e598

相关文章

代码示例:Python 调用并执行 JS

经常做爬虫需要扣JS的老铁一定很熟悉这段操作,通过execjs调用并执行 JS 对一些加解密的处理非常有用。在此记录一下相互学习交流。以下是具体步骤:1、安装 execjspip install py...

如何使用 Scrapy 执行 JavaScript

大多数现代网站都使用客户端 JavaScript 框架,例如 React、Vue 或 Angular。在没有服务器端渲染的情况下从动态网站抓取数据通常需要执行 JavaScript 代码。我已经抓取了...

Python爬虫高级之JS渗透登录新浪微博 | 知了独家研究

小伙伴们看到标题可能会想,我能直接自己登陆把登陆后的cookie复制下来加到自定义的请求头里面不香嘛,为什么非要用python模拟登录的过程?如果我们是长期爬取数据,比如每天早上中午和晚上定时爬取新浪...

Python、JavaScript和Rust的Web性能比较

Python使用FastApi测试;Node.JS使用Fastify;Rust则使用Actix。选择的Python和Node框架,是在搜索 "最快的<某语言>api "时得...

在pyside的QWebEngineView中和javascript通信

在pyside2中可以使用QtWebChannel 使QWebEngineView和前端页面的javasccript通信代码:from PySide2.QtWebChannel import QWeb...

网页数据如何获取,带你走近JS逆向,完全入门级!

在这个大数据时代,我们眼睛所看到的百分之九十的数据都是通过页面呈现出现的,不论是PC端、网页端还是移动端,数据渲染还是基于html/h5+javascript进行的,而大多数的数据都是通过请求后台接口...