Pythonmonkey是一种Mozilla Spidermonkey JavaScript引擎,该引擎嵌入了Python运行时,使用Python引擎提供JavaScript主机环境。
我们使用CPYTHON C API在Python列表和词典上实现的JavaScript数组和对象方法,并使用Mozilla Firefox Spidermonkey Javascript C ++ API进行逆。
截至2024年9月,该项目已达到MVP。该项目正在通过分布式维护。
欢迎和鼓励外部贡献和反馈。
$ pip install pythonmonkey from pythonmonkey import eval as js_eval
js_eval ( "console.log" )( 'hello, world' )eval()函数,该功能接受JS代码并返回JS-> Python强制值require功能,返回模块导出的强制性如果要构建本地版本,请阅读此内容。
您将需要以下安装(可以通过运行./setup.sh自动完成):
运行poetry install 。该命令自动编译项目并将项目以及依赖项安装到诗歌Virtualenv中。如果您想构建文档,请设置BUILD_DOCS环境变量,例如: BUILD_DOCS=1 poetry install 。 Pythonmonkey支持多种构建类型,您可以通过设置BUILD_TYPE环境变量来构建它们,例如: BUILD_TYPE=Debug poetry install 。构建类型是(不敏感的):
Release :剥离符号,最大优化(默认)DRelease :与Release相同,除了符号未剥离Debug :最小优化Sanitize :与Debug相同,除了启用了地址齐射器Profile :与Debug相同,除了启用了分析None :不要编译(如果您只想构建文档,则有用)如果您使用的是VSCODE,则只需按Ctrl + Shift + B即可运行构建任务 - 我们拥有为您配置的tasks.json 。
poetry install --no-root --only=devpoetry run pytest ./tests/pythonpoetry run bash ./peter-jr ./tests/js/对于类似于构建任务的VSCODE用户,我们可以使用一个测试任务。
在安装过程中需要NPM(NODE.JS)才能填充JS依赖项。
$ pip install pythonmonkey$ pip install --extra-index-url https://nightly.pythonmonkey.io/ --pre pythonmonkey一旦您使用诗歌编写了项目, pythonmonkey就可以在Virtualenv中获得。
$ poetry run python Python 3.10 .6 ( main , Nov 14 2022 , 16 : 10 : 14 ) [ GCC 11.3 .0 ] on linux
Type "help" , "copyright" , "credits" or "license" for more information .
> >> import pythonmonkey as pm
>> > hello = pm . eval ( "() => {return 'Hello from Spidermonkey!'}" )
>> > hello ()
'Hello from Spidermonkey!'另外,您可以通过运行来构建可安装的软件包
$ cd python/pminit && poetry build --format=sdist && cd - && mv -v python/pminit/dist/ * ./dist/
$ poetry build --format=wheel并通过pip install ./dist/*安装它们。
安装pythonmonkey还将安装pminit软件包作为依赖项。但是, pip uninstall不会自动删除其依赖关系。
如果您想从系统中清除pythonmonkey ,请执行以下操作:
$ pip uninstall pythonmonkey pminitpoetry run gdb python 。参见Python Wiki:debuggingwithgdb如果您使用的是VSCODE,则在VSCODE的内置调试器中进行调试更加方便。只需在编辑器中的一个打开的Python文件上按F5即可开始调试launch.json文件为您配置。
这些方法是从Pythonmonkey模块导出的。请参阅Python/Pythonmonkey/Pythonmonkey.pyi中的定义。
评估JavaScript代码。该评估的语义与JavaScript中使用的评估非常相似。 code字符串中评估的最后一个表达式用作此函数的返回值。要在严格的模式下评估code ,第一个表达式应为字符串"use strict" 。
评估函数支持一个可以影响JS代码以强大方式评估JS代码的选项对象。它们主要基于Spidermonkey的CompileOptions 。支持的选项键是:
filename :设置此代码的文件名,以生成堆栈跟踪等。lineno :设置该代码的行号偏移,以生成堆栈跟踪等。column :设置此代码的列号偏移,以生成堆栈跟踪等。mutedErrors :如果设置为True ,则忽略了评估错误或未手持拒绝(“静音”)。默认False 。noScriptRval :如果False ,请将脚本的最后一个表达式值作为结果值返回给呼叫者。默认False 。selfHosting :实验strict :在严格的模式下强行评估( "use strict" )。默认False 。module :指示该文件是一个eCmasixt模块(始终严格的模式代码,并且不允许HTML注释)。默认False 。fromPythonFrame :基于Python调用评估的位置生成相当于文件名,lineno和列的等效物。这使得评估Python多行字母文字并在JS中生成堆栈跟踪,以指向Python源文件中的错误。 undefined ;如果要返回函数,则必须评估一个表达式: pythonmonkey . eval ( "myFunction() { return 123 }; myFunction" ) pythonmonkey . eval ( "(myFunction() { return 123 })" ) pythonmonkey . eval ( "(thing) => console.log('you said', thing)" )( "this string came from Python" )使用标准CommonJS语义返回由moduleIdentifier识别的commonjs模块的出口
require.js -JavaScript模块;源代码装饰exports对象.py -Python模块;源代码装饰exports dict.json -JSON模块;导出是在文件中解析JSON文本的结果python dict等同于JavaScript中的全球对象。
返回新需求功能的工厂功能
加载并评估程序(主)模块。程序模块必须用JavaScript编写。除非程序的主要入口点是用JavaScript编写的,否则程序模块是不需要的。
应注意确保每个JS上下文仅运行一个程序模块。
如果字符串可能成为有效的JS语句,则检查字符串code并返回false,并增加了更多行。 PMJ在内部使用它,对于构建JavaScript Repls可能非常有帮助;这个想法是在缓冲区中积聚线,直到IscompilableUnit为真,然后评估整个缓冲区。
返回一个python函数,该功能使用JS新运算符调用function 。
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
{}
>> >这是包裹在功能中的JS typeof操作员,因此可以从Python轻松使用它。
所有JS标准类(数组,函数,对象,日期...)和对象(Globalthis,cinalizationRegistry ...)均以Pythonmonkey模块的导出提供。这些导出是通过在当前蜘蛛网上下文中列举全局变量来生成的。当前列表是:
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,deodeuricomponent,encodeuricomponent,function,object,debuggerglobal,ofderizationRegistry,array,globalthisthisthis
请参阅Python/Pythonmonkey/global.d.ts中的定义。包括:
consoleatobbtoasetTimeoutclearTimeout通过调用(Python)PythonMonKey模块的require或createRequire出口来激活COMONJS子系统。
requireexportsmodule__filename__dirnamepython.print python打印功能python.getenv python getenv函数python.stdout带有read方法write对象,读写到stdoutpython.stderr带有read方法write对象,读写到stderrpython.exec python exec函数python.eval python评估功能python.exit通过sys.exit()退出;退出代码是函数参数或python.exit.code 。python.paths python sys.paths列表,在JS中可见为数组将变量从Python发送到JavaScript时,Pythonmonkey将根据其类型巧妙地胁迫或包装您的变量。 Pythonmonkey将共享CTYPE,键入数组和字符串的备用商店(使用相同的内存);由于不涉及复制,因此在语言障碍中移动这些类型非常快。
注意: Python 3.12(PEP 623)中有一些计划更改内部字符串表示形式,以便字符串中的每个字符都使用四个字节内存。这将破坏pythonmonkey的快速字符串传输,因为它依赖于python和javaScript中的内存布局相同。在撰写本文时(2023年7月),“经典” python弦仍然在3.12 Beta版本中工作。
在不可能共享的备份商店的情况下,Pythonmonkey将自动散发使用“真实”数据结构作为其价值权威的包装器。仅复制不变的内在物质。这意味着,如果您更新JavaScript中的对象,则将更新Python中的相应dict,等等。
JavaScript数组和对象方法在Python列表和词典上实现,反之亦然。
| Python类型 | JavaScript类型 |
|---|---|
| 细绳 | 细绳 |
| 整数 | 数字 |
| 布尔 | 布尔 |
| 功能 | 功能 |
| dict | 目的 |
| 列表 | 大批 |
| DateTime | 日期对象 |
| 等待 | 承诺 |
| 错误 | 错误对象 |
| 缓冲 | ArrayBuffer |
| JavaScript类型 | Python类型 |
|---|---|
| 细绳 | pythonmonkey.jsstringproxy(字符串) |
| 数字 | 漂浮 |
| bigint | pythonmonkey.bigint(整数) |
| 布尔 | 布尔 |
| 功能 | pythonmonkey.jsfunctionproxy |
| 对象 - 大多数 | pythonmonkey.jsobjectproxy(dict) |
| 对象 - 日期 | DateTime |
| 对象 - 数组 | pythonmonkey.jsarrayproxy(列表) |
| 对象 - 承诺 | 等待 |
| 对象 - arraybuffer | 缓冲 |
| 对象 - 类型数组 | 缓冲 |
| 对象 - 错误 | 错误 |
您可以将JavaScript中的数字施加到Bigint:
function myFunction ( a , b ) {
const result = calculate ( a , b ) ;
return BigInt ( Math . floor ( result ) ) ;
} pythonmonkey.bigint对象像python中的int一样起作用,但它将被强制为JavaScript中的bigint:
import pythonmonkey
def fn myFunction ()
result = 5
return pythonmonkey . bigint ( result )您可以使用JavaScript IIFE创建一个范围,您可以在其中注入Python符号:
globalThis . python . exit = pm . eval ( """'use strict';
(exit) => function pythonExitWrapper(exitCode) {
if (typeof exitCode === 'number')
exitCode = BigInt(Math.floor(exitCode));
exit(exitCode);
}
""" )( sys . exit );您需要一个活动环境来使用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 ())基本的JavaScript外壳pmjs ,与Pythonmonkey船。该外壳可以充当补充或运行JavaScript程序;它在概念上类似于带有node.js的node壳。
PMJS启动了Pythonmonkey的CommonJS子系统,该系统允许其使用commonjs模块,其语义与node.js相似。有关支持功能的完整列表,请参见CTX模块。
除了用JavaScript编写的commonjs模块外,pythonmonkey还支持用python编写的commonjs模块。只需在带有.py扩展名的文件中装饰一个命名的命名exports ,就可以通过require()加载javascript或python。
程序模块或主模块是COMPONJ中的特殊模块。在程序模块中:
globalThis的属性arguments变量,该数组保存您的程序的参数向量(命令行参数) $ echo " console.log('hello world') " > my-program.js
$ pmjs my-program.js
hello world
$ // date-lib.js - require("./date-lib")
const d = new Date ( ) ;
exports . today = ` ${ d . getFullYear ( ) } - ${ String ( d . getMonth ( ) ) . padStart ( 2 , '0' ) } - ${ String ( d . getDay ( ) ) . padStart ( 2 , '0' ) } ` # date-lib.py - require("./date-lib")
from datetime import date # You can use Python libraries.
exports [ 'today' ] = date . today ()如果您在commonjs需要函数方面遇到麻烦,请设置环境变量DEBUG='ctx-module*' ,您可以看到它试图加载的文件名。
Pythonmonkey拥有一个类似GDB的JavaScript命令行调试器,名为PMDB ,该debugger;陈述和无人例外。
要启用PMDB ,只需from pythonmonkey.lib import pmdb; pmdb.enable()在Pythonmonkey上做任何事情之前, from pythonmonkey.lib import pmdb; pmdb.enable() 。
import pythonmonkey as pm
from pythonmonkey . lib import pmdb
pmdb . enable ()
pm . eval ( "..." )在PMDB中运行help命令以查看可用命令。
(pmdb) > help
List of commands:
• ...
• ... .help菜单--help命令行选项--inspect选项启用PMDB ,类似GDB的JavaScript命令行调试器-r选项可用于加载程序或REPP运行之前的模块-e选项评估代码 - 例如定义全局变量 - 在您的程序或depl运行之前$1 , $2等的变量中。 $ pmjs
Welcome to PythonMonkey v1.0.0.
Type ".help" for more information.
> .python import sys
> .python sys.path
$1 = { '0': '/home/wes/git/pythonmonkey2',
'1': '/usr/lib/python310.zip',
'2': '/usr/lib/python3.10',
'3': '/usr/lib/python3.10/lib-dynload',
'4': '/home/wes/.cache/pypoetry/virtualenvs/pythonmonkey-StuBmUri-py3.10/lib/python3.10/site-packages',
'5': '/home/wes/git/pythonmonkey2/python' }
> $1 [3]
'/usr/lib/python3.10/lib-dynload'
>