Pythonmonkey - это двигатель Mozilla Spidermonkey JavaScript, встроенный во время выполнения Python, используя двигатель Python для обеспечения среды хоста JavaScript.
Мы показываем массив JavaScript и методы объектов, реализованные в списке Python и словарных словари с использованием API CPYTHON C, и обратного с использованием API Mozilla Firefox Spidermonkey JavaScript C ++.
Этот проект достиг MVP по состоянию на сентябрь 2024 года. Он находится под техническим обслуживанием.
Внешние взносы и обратная связь приветствуются и поощряются.
$ pip install pythonmonkey from pythonmonkey import eval as js_eval
js_eval ( "console.log" )( 'hello, world' )eval() в Python, которая принимает код JS и возвращает значения JS-> Python Custerrequire функции, возвращает принудительный DICT экспорта модулейПрочитайте это, если вы хотите построить локальную версию.
Вам понадобится следующее установленное (которое можно сделать автоматически с помощью ./setup.sh ):
Запустить poetry install . Эта команда автоматически компилирует проект и устанавливает проект, а также зависимости в поэзию Virtualenv. Если вы хотите построить документы, установите переменную среды BUILD_DOCS , например,: BUILD_DOCS=1 poetry install . Pythonmonkey поддерживает несколько типов сборки, которые вы можете построить, установив переменную среды BUILD_TYPE , например, SO: 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: отладка withgdb Если вы используете VSCODE, это удобнее отладки в встроенном отладчике VSCODE. Просто нажмите F5 в файле Open Python в редакторе, чтобы начать отладку - у нас есть файл launch.json для вас.
Эти методы экспортируются из модуля Pythonmonkey. См. Определения в Python/Pythonmonkey/Pythonmonkey.pyi.
Оценить код JavaScript. Семантика этой оценки очень похожа на оценку, используемой в JavaScript; Последнее выражение, оцениваемое в строке code , используется в качестве возвращаемого значения этой функции. Чтобы оценить code в строгом режиме, первым выражением должно быть строка "use strict" .
Функция Eval поддерживает объект параметров, который может повлиять на то, как код JS оценивается мощными способами. Они в значительной степени основаны на CompileOptions Spidermonkey. Поддерживаемые клавиши опции:
filename : Установите имя файла этого кода для целей генерации трассов стека и т. Д.lineno : Установите смещение номера строки этого кода для целей генерации трассов стека и т. Д.column : Установите смещение номера столбца этого кода для целей генерации трассов стека и т. Д.mutedErrors : если установить на True , оценивают ошибки или нездоровые отказа («приглушен»). По умолчанию False .noScriptRval : если False верните последнее значение выражения сценария в качестве значения результата для вызывающего абонента. По умолчанию False .selfHosting : экспериментальныйstrict : насильно оценивать в строгом режиме ( "use strict" ). По умолчанию False .module : укажите, что файл является модулем Ecmascript (всегда строгий код режима и запрещайте HTML -комментарии). По умолчанию False .fromPythonFrame : генерируйте эквивалент имени файла, линьено и столбца на основе местоположения вызова Python для оценки. Это позволяет оценить литералы Python Multiline String и генерировать трассировки стека в JS, указывающих на ошибку в исходном файле Python. undefined в JavaScript; Если вы хотите вернуть функцию, вы должны оценить выражение: 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 , с использованием стандартной семантики CommonJSS
require файла Python..js - модуль JavaScript; исходный код украшает объект exports.py - модуль Python; исходный код украшает exports DICT.json - json module; Экспорт является результатом анализа текста JSON в файлеДикт Python, который эквивалентен глобальному объекту в JavaScript.
Заводская функция, которая возвращает новую функцию потребности
Загрузить и оценить модуль программы (основной). Программные модули должны быть написаны в JavaScript. Программные модули не являются необходимыми, если только основная точка записи вашей программы не написана в JavaScript.
Следует заботиться, чтобы гарантировать, что только один программный модуль запускается в соответствии с контекстом JS.
Проверка строкового code и возвращает False, если строка может стать действительным оператором JS с добавлением большего количества строк. Это используется внутри PMJS и может быть очень полезным для создания Speps JavaScript; Идея состоит в том, чтобы накапливать линии в буфере, пока не станет истина, а затем оценить весь буфер.
Возвращает функцию Python, которая вызывает function с новым оператором JS.
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, завершающая регистрация ...) доступны в качестве экспорта модуля 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, слабая карта, карта, набор, dataview, символ, Intl, отражение, слабый, обещание, webassembly, sleedref, итератор, асинцитер, nan, insenan, isfinite, parsefloat, parseint, resec Decodeuricomponent, Encodeuricomponent, Function, Object, Debuggerglobal, завершающий регистр, массив, GlobalThis
См. Определения в Python/Pythonmonkey/Global.d.ts. Включая:
consoleatobbtoasetTimeoutclearTimeout Подсистема CommonJS активируется путем вызывы экспорта require или createRequire модуля PythonMonkey.
requireexportsmodule__filename__dirnamepython.print - функция печати Pythonpython.getenv - функция Python getenvpython.stdout - объект с методами read и write , который читает и пишет в stdoutpython.stderr - объект с методами read и write , который читает и пишет в Stderrpython.exec - функция Exec Pythonpython.eval - функция Python Evalpython.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 г.) «классические» струны питона все еще работают в бета -выпусках 3.12.
Там, где общий магазин поддержки невозможна, Pythonmonkey автоматически испускает обертки, которые используют «реальную» структуру данных в качестве своей стоимости авторитета. Только неизменная внутренняя часть скопирована. Это означает, что если вы обновляете объект в JavaScript, соответствующий дикт в Python будет обновлен и т. Д.
Массив JavaScript и методы объектов реализованы в списке и словарях Python, а также наоборот.
| Тип питона | JavaScript Тип |
|---|---|
| Нить | нить |
| Целое число | число |
| Буль | логический |
| Функция | функция |
| Диктат | объект |
| Список | Множество |
| DateTime | Дата объекта |
| ожидается | Обещать |
| Ошибка | Объект ошибки |
| Буфер | Arraybuffer |
| JavaScript Тип | Тип питона |
|---|---|
| нить | pythonmonkey.jsstringproxy (String) |
| число | Плавать |
| 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 работает как int in python, но он будет принужден как Bigint в JavaScript:
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 Repl или запуска JavaScript; Это концептуально похоже на оболочку node , которая поставляется с Node.js.
PMJS начинает подсистему Pythonmonkey CommonJS, которая позволяет использовать модули CommonJS, с семантикой, похожими на Node.js - например, модуль поиска. Путы, Понимание Package.json, index.js и так далее. См. CTX-модуль для полного списка поддерживаемых функций.
В дополнение к модулям CommonJS, написанным в JavaScript, Pythonmonkey поддерживает модули CommonJS, написанные на Python. Просто украсьте дикта с именем exports внутри файла с расширением .py , и он может быть загружен с помощью require() - в JavaScript или Python.
Программный модуль, или основной модуль, является специальным модулем в CommonJS. В программном модуле:
globalThisarguments переменная в массиве, которая содержит вектор аргументов вашей программы (аргументы командной строки) $ 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 Command-Line под названием PMDB , который будет автоматически запустить от debugger; заявления и непредучанные исключения.
Чтобы включить PMDB , просто позвоните from pythonmonkey.lib import pmdb; pmdb.enable() , прежде чем что -то делать на Pythonmonkey.
import pythonmonkey as pm
from pythonmonkey . lib import pmdb
pmdb . enable ()
pm . eval ( "..." ) Запустите команду help в PMDB , чтобы увидеть доступные команды.
(pmdb) > help
List of commands:
• ...
• ... .help--help--inspect включает PMDB , GDB-подобный отладчик командной строки JavaScript-r может использоваться для загрузки модуля перед вашей программой или запуска REPL-e можно использовать оценку кода -например, определить глобальные переменные -до вашей программы или запуска запуска$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'
>