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'
>