O Pythonmonkey é um mecanismo JavaScript Mozilla Spidermonkey incorporado no tempo de execução do Python, usando o mecanismo Python para fornecer o ambiente do host JavaScript.
Apresentamos métodos de matriz JavaScript e objetos implementados na lista de Python e dicionários usando a API Cpython C, e o inverso usando o API C ++ do Mozilla Firefox Spidermonkey JavaScript C ++.
Este projeto atingiu o MVP em setembro de 2024. Está sob manutenção por distributiva.
Contribuições e feedback externos são bem -vindos e incentivados.
$ pip install pythonmonkey from pythonmonkey import eval as js_eval
js_eval ( "console.log" )( 'hello, world' )eval() Função em Python, que aceita o código JS e retorna JS-> valores coagidos por Pythonrequire função, retorna um ditado coagido das exportações de módulosLeia isso se quiser criar uma versão local.
Você precisará do seguinte instalado (que pode ser feito automaticamente executando ./setup.sh ):
Execute poetry install . Este comando compila automaticamente o projeto e instala o projeto, bem como dependências na poesia virtualenv. Se você deseja construir os documentos, defina a variável de ambiente BUILD_DOCS , como assim: BUILD_DOCS=1 poetry install . O PythonMonKey suporta vários tipos de construção, que você pode criar definindo a variável de ambiente BUILD_TYPE , como assim: BUILD_TYPE=Debug poetry install . Os tipos de construção são (insensíveis ao caso):
Release : Símbolos despojados, otimizações máximas (padrão)DRelease : o mesmo que Release , exceto os símbolos não são despojadosDebug : otimizações mínimasSanitize : o mesmo que Debug , exceto com o endereço de endereço ativadoProfile : o mesmo que Debug , exceto o perfil está ativadoNone : não compilar (útil se você deseja construir apenas os documentos) Se você estiver usando o VSCode, basta pressionar Ctrl + Shift + B para executar a tarefa de compilação - temos o arquivo tasks.json configurado para você.
poetry install --no-root --only=devpoetry run pytest ./tests/pythonpoetry run bash ./peter-jr ./tests/js/Para usuários do VSCODE, semelhante à tarefa de compilação, temos uma tarefa de teste pronta para uso.
O NPM (Node.js) é necessário durante a instalação apenas para preencher as dependências do JS.
$ pip install pythonmonkey$ pip install --extra-index-url https://nightly.pythonmonkey.io/ --pre pythonmonkey pythonmonkey está disponível na poesia VirtualEnv depois que você compilou o projeto usando poesia.
$ 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!'Como alternativa, você pode criar pacotes instaláveis executando
$ cd python/pminit && poetry build --format=sdist && cd - && mv -v python/pminit/dist/ * ./dist/
$ poetry build --format=wheel e instale -os por pip install ./dist/* .
A instalação pythonmonkey também instalará o pacote pminit como uma dependência. No entanto, pip uninstall um pacote não removerá automaticamente suas dependências.
Se você deseja remover de maneira limpa pythonmonkey do seu sistema, faça o seguinte:
$ pip uninstall pythonmonkey pminitpoetry run gdb python . Veja Python Wiki: Debuggingwithgdb Se você estiver usando o VSCode, é mais conveniente depurar no depurador interno do VSCODE. Basta pressionar F5 em um arquivo Python aberto no editor para iniciar a depuração - temos o arquivo launch.json configurado para você.
Esses métodos são exportados do módulo Pythonmonkey. Veja definições em python/pythonmonkey/pythonmonkey.pyi.
Avalie o código JavaScript. A semântica desta avaliação é muito semelhante à avaliação usada no JavaScript; A última expressão avaliada na sequência code é usada como o valor de retorno desta função. Para avaliar code no modo rigoroso, a primeira expressão deve ser a string "use strict" .
A função Eval suporta um objeto de opções que pode afetar como o código JS é avaliado de maneiras poderosas. Eles são amplamente baseados nas CompileOptions de Spidermonkey. As chaves de opção suportadas são:
filename : defina o nome do arquivo deste código para fins de geração de rastreamentos de pilha etc.lineno : Defina o deslocamento do número da linha deste código para fins de geração de traços de pilha etc.column : Defina o deslocamento do número da coluna deste código para fins de geração de traços de pilha etc.mutedErrors : Se definido como True , avaliar erros ou rejeições não atendidas são ignoradas ("silenciadas"). Padrão False .noScriptRval : se False , retorne o último valor de expressão do script como o valor do resultado para o chamador. Padrão False .selfHosting : Experimentalstrict : Avalie à força no modo rigoroso ( "use strict" ). Padrão False .module : Indique que o arquivo é um módulo ECMAScript (sempre o código de modo rigoroso e proibiu os comentários HTML). Padrão False .fromPythonFrame : Gere o equivalente ao nome do arquivo, lineno e coluna com base na localização da chamada Python para avaliar. Isso possibilita avaliar literais de cordas multilinas Python e gerar rastreamentos de pilha em JS apontando para o erro no arquivo de origem Python. undefined em JavaScript; Se você deseja retornar uma função, deve avaliar uma expressão: pythonmonkey . eval ( "myFunction() { return 123 }; myFunction" ) pythonmonkey . eval ( "(myFunction() { return 123 })" ) pythonmonkey . eval ( "(thing) => console.log('you said', thing)" )( "this string came from Python" ) Retorne as exportações de um módulo Commonjs identificado pelo moduleIdentifier , usando a semântica do Commonjs Standard
require.js - módulo JavaScript; O código -fonte decora o objeto exports.py - módulo python; O código -fonte decora exports dicadas.json - módulo json; As exportações são o resultado de analisar o texto JSON no arquivoUm ditado de python que é equivalente ao objeto global deste objeto em JavaScript.
Função de fábrica que retorna uma nova função exigida
Carregue e avalie um módulo de programa (principal). Os módulos do programa devem ser gravados em JavaScript. Os módulos do programa não são necessários, a menos que o ponto de entrada principal do seu programa esteja escrito no JavaScript.
Deve -se tomar cuidado para garantir que apenas um módulo de programa seja executado por contexto JS.
Examina o code da string e retorna false se a string puder se tornar uma instrução JS válida com a adição de mais linhas. Isso é usado internamente pelos PMJs e pode ser muito útil para a construção de REPLs JavaScript; A idéia é acumular linhas em um buffer até que o ISComPilableUnit seja verdadeiro e avaliar todo o buffer.
Retorna uma função python que chama function com o novo operador 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
{}
>> > Este é o operador JS typeof , embrulhado em uma função para que possa ser usado facilmente a partir do Python.
Todas as classes padrão JS (Array, Função, Objeto, Data ...) e Objetos (Global This, FinalizationRegistry ...) estão disponíveis como exportações do módulo PythonMonkey. Essas exportações são geradas enumerando a variável global no contexto atual do Spidermonkey. A lista atual é:
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, codeuri, decodeuricomponent, codeuricomponent, função, objeto, depurglobal, FinalizationRegistry, Array, GlobalThis
Consulte Definições em Python/Pythonmonkey/global.d.ts. Incluindo:
consoleatobbtoasetTimeoutclearTimeout O subsistema Commonjs é ativado invocando as exportações require ou createRequire do módulo PythonMonkey (Python).
requireexportsmodule__filename__dirnamepython.print - A função de impressão Pythonpython.getenv - a função Python Getenvpython.stdout - um objeto com métodos read e write , que leem e escrevem para stdoutpython.stderr - um objeto com métodos read e write , que leem e escrevem para Stderrpython.exec - a função Python Execpython.eval - a função de avaliação pythonpython.exit - saída via sys.exit (); O código de saída é o argumento da função ou python.exit.code .python.paths - A lista Python Sys.Paths, visível em JS como uma matriz Ao enviar variáveis do Python para o JavaScript, o Pythonmonkey coagirá ou envolverá suas variáveis com base no tipo deles. O Pythonmonkey compartilhará lojas de apoio (use a mesma memória) para ctypes, matrizes digitadas e strings; Mover esses tipos em toda a barreira do idioma é extremamente rápido porque não há cópia envolvida.
Nota: Existem planos no Python 3.12 (PEP 623) para alterar a representação interna da string, para que todo caractere da string use quatro bytes de memória. Isso quebrará transferências rápidas de string para o Pythonmonkey, pois se baseia no layout da memória sendo o mesmo em Python e JavaScript. Até o momento em que este artigo foi escrito (julho de 2023), as cordas Python "clássicas" ainda funcionam nos lançamentos beta 3.12.
Onde a loja de apoio compartilhada não é possível, o Pythonmonkey emitirá automaticamente invólucros que usam a estrutura de dados "real" como sua autoridade de valor. Apenas intrínsecos imutáveis são copiados. Isso significa que, se você atualizar um objeto em JavaScript, o ditado correspondente no Python será atualizado, etc.
Os métodos de JavaScript Array e Object são implementados na lista e dicionários Python, e vice-versa.
| Tipo Python | Tipo de JavaScript |
|---|---|
| Corda | corda |
| Inteiro | número |
| Bool | booleano |
| Função | função |
| Dito | objeto |
| Lista | Variedade |
| DateTime | Objeto de data |
| aguardável | Promessa |
| Erro | Objeto de erro |
| Buffer | ArrayBuffer |
| Tipo de JavaScript | Tipo Python |
|---|---|
| corda | pythonmonkey.jsstringproxy (string) |
| número | Flutuador |
| bigint | pythonmonkey.bigint (número inteiro) |
| booleano | Bool |
| função | pythonmonkey.jsfunctionProxy |
| objeto - a maioria | pythonmonkey.jsobjectproxy (dict) |
| Objeto - Data | DateTime |
| Objeto - Array | pythonmonkey.jsarrayproxy (lista) |
| Objeto - Promise | aguardável |
| Objeto - ArrayBuffer | Buffer |
| Objeto - Tipo matrizes | Buffer |
| objeto - erro | Erro |
Você pode forçar um número em JavaScript a ser coagido como um número inteiro, lançando -o para Bigint:
function myFunction ( a , b ) {
const result = calculate ( a , b ) ;
return BigInt ( Math . floor ( result ) ) ;
} O objeto pythonmonkey.bigint funciona como um int em Python, mas será coagido como um bigint em JavaScript:
import pythonmonkey
def fn myFunction ()
result = 5
return pythonmonkey . bigint ( result )Você pode usar um iife JavaScript para criar um escopo no qual você pode injetar símbolos 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 ); Você precisa de um loop de eventos em execução para usar setTimeout e Promise <=> awaitable coerção.
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 ()) Um shell javascript básico, pmjs , navios com Pythonmonkey. Este shell pode atuar como um repl ou executar programas JavaScript; É conceitualmente semelhante ao shell node que é enviado com o Node.JS.
O PMJS inicia o subsistema Commonjs da PythonMonkey, que permite usar os módulos Commonjs, com semântica semelhante ao Node.js - por exemplo, módulo de pesquisa.paths, compreensão package.json, index.js e assim por diante. Consulte o módulo CTX para obter uma lista completa de recursos suportados.
Além dos módulos Commonjs escritos em JavaScript, o PythonMonkey suporta módulos Commonjs escritos em Python. Basta decorar um ditado denominado exports dentro de um arquivo com uma extensão .py , e ele pode ser carregado por require() - em JavaScript ou Python.
O módulo do programa, ou módulo principal, é um módulo especial no Commonjs. Em um módulo de programa:
globalThisarguments em uma matriz que mantém o vetor de argumento do seu programa (argumentos da linha de comando) $ 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 () Se você estiver tendo problemas com o Commonjs, requer função, defina a variável de ambiente DEBUG='ctx-module*' e poderá ver os nomes de arquivos que ele tenta carregar.
O Pythonmonkey possui um depurador de linha de comando JavaScript do tipo GDB, chamado PMDB , que seria automaticamente acionado no debugger; declarações e exceções não capturadas.
Para ativar o PMDB , basta ligar from pythonmonkey.lib import pmdb; pmdb.enable() antes de fazer qualquer coisa no Pythonmonkey.
import pythonmonkey as pm
from pythonmonkey . lib import pmdb
pmdb . enable ()
pm . eval ( "..." ) Execute o comando help no PMDB para ver os comandos disponíveis.
(pmdb) > help
List of commands:
• ...
• ... .help no repl--help--inspect permite que o PMDB , um depurador de linha de comando JavaScript do tipo GDB-r pode ser usada para carregar um módulo antes do seu programa ou das execuções Repl-e pode ser usada Código de Avaliar -por exemplo, Definir variáveis globais -antes do seu programa ou das execuções Replic$1 , $2 , etc. $ 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'
>