Bygger bro mellom JavaScript og Python med «PythonMonkey»

PythonMonkey lar deg kjøre JavaScript-kode i Python, og motsatt. Nå er snart versjon 1.0 klar.

PythonMonkey skal la deg kjøre JavaScript-kode fra Python, og motsatt. 📸: Skjermbilde fra pythonmonkey.io
PythonMonkey skal la deg kjøre JavaScript-kode fra Python, og motsatt. 📸: Skjermbilde fra pythonmonkey.io Vis mer

Hva om du kunne kjøre JavaScript-kode i et Python-program, eller Python-kode i et JavaScript-program? Det er nettopp det kanadiske selskapet Distributive tar sikte på med PythonMonkey, skriver The New Stack.

PythonMonkey er en Mozilla SpiderMonkey-JavaScript-motor som er bygget inn i en Python-runtime.

– Det vil for eksempel være mulig å kalle Python-pakker som NumPy fra et JavaScript-bibliotek, eller bruke NPM-pakker som crypto-js direkte fra Python, skriver Will Pringle, utvikler hos Distributive.

PythonMonkey ble annonsert for rundt ett år siden, og ifølge The New Stack er planen å lansere versjon 1.0 neste måned.

Trengte det selv

PythonMonkey ble laget av Distributive fordi de selv hadde bruk for det. Selskapet ønsket å porte sitt JavaScript/Node.js-SDK direkte til Python uten å måtte vedlikeholde to kodebaser.

– Vi håper PythonMonkey vil hjelpe til med å bygge bro mellom millioner av NPM-pakker og Python-utviklere, og også potensielt en dag stå på egne ben som en egen JavaScript-runtime som kan konkurere med Node.js, Bun og Deno – men med mulighet til å bruke en "hvilken som helst" Python-pakke fra JavaScript, sier Pringle til The New Stack.

«Vi håper PythonMonkey vil hjelpe til med å bygge bro mellom millioner av NPM-pakker og Python-utviklere.»

Med PythonMonkey skal det ifølge Pringle også være enkelt å kjøre WebAssembly-moduler (Wasm) i Python via WebAssembly-API-et og motoren i SpiderMonkey. Takket være WebAssembly-motoren i Mozillas SpiderMonkey vil Wasm-kode skrevet i språk som C, C++ eller Rust kunne kjøres trygt i en sandkasse.

– I tillegg vil utviklere kunne bruke PythonMonkey til å refaktorere en treg "hot loop" (en løkke som kjører veldig ofte. Red. anm.) skrevet i Python til å bruke JS i stedet, og utnytte SpiderMonkeys "just-in-time"-kompilator for nesten "native" ytelse, skriver Pringle.

Slik virker det

Her er et eksempel på hvordan du kan importere og kjøre en JavaScript-fil fra Python, hentet fra Pringles bloggpost:

my-javascript-module.js:

exports.sayHello = () => { console.log('hello, world') };

main.py:

import pythonmonkey as pm
test = pm.require('./my-javascript-module');
test.sayHello() # this prints hello, world

Og motsatt vei – her er hvordan du laster en Python CommonJS-modul fra JavaScript:

my-python-module.py:

def getStringLength(s):
  return len(s)

exports['getStringLength'] = getStringLength

my-javascript-module.js:

const { getStringLength } = require('./my-python-module');

function printStringLength(s) {
  console.log(`String: "${s}" has a length of ${getStringLength(s)}`);
}

module.exports = { printStringLength, };

main.py:

import pythonmonkey as pm
test = pm.require('./my-javascript-module');
test.printStringLength("Hello, world!") # String: "Hello, world!" has a length of 13

Pringle har tidligere sagt at det står på planen å også støtte import av Python-moduler i JavaScript via ESM-syntaksen.

På PythonMonkeys GitHub og dokumentasjonssider oppgir Distributive at noen av målene med prosjektet er:

  • Raskt og minneeffektivt
  • Utviklere kan velge å kode i JS eller Python alt ettersom hva de selv foretrekker
  • Bruk JS-biblioteker fra Python
  • Bruk Python-biblioteker fra JS
  • Samme prosess kjører både JavaScript- og Python virtuelle maskiner
  • Python Lists og Dicts oppfører seg som JavaScript Arrays og Objects, og motsatt – og tilpasser seg automatisk avhengig av kontekst

Flere konkurrenter

Det bør nevnes at det allerede finnes flere andre prosjekter for å kjøre JavaScript i Python, som JS2PY, PyV8 og Metacall.

Pringle mener imidlertid at PythonMonkey har en rekke fordeler fremfor disse. For eksempel er JS2Py skrevet utelukkende i Python, mens Pringle mener det er bedre å bruke en robust og kontinuerlig oppdatert og rask JavaScript-motor som SpiderMonkey eller V8.

PyV8 og CloudFlares implementasjon av den er på sin side en Python-wrapper for Googles V8 JavaScript-motor, og opererer på et lavere nivå enn PythonMonkey. Det gjør at du blant annet ikke får støtte for JavaScript-funksjonalitet som promises og async/await.

Til slutt nevner han Metacall, som støtter interoperabilitet mellom en masse forskjellige programmeringsspråk og Python – men der den omfattende språkstøtten kommer med en del ulemper, som at man må installere programvare utover Python-pakken for at det skal fungere. I tillegg er ytelsen dårligere, hevder Pringle.

– Men selv om alternative prosjekter har likheter med PythonMonkeys modell, kommer de til kort når det gjelder PythonMonkeys interoperabilitet, brukervennlighet og ytelse, skriver Pringle.