На цій сторінці побудовано програму, яка в одному процесі використовує пакет npm із JavaScript і пакет PyPI з Python.
| Що потрібно | Як |
|---|---|
| Python | elide setup python; elide info показує python у розділі Languages |
| Виклики між мовами | --interop під час кожного запуску; налаштування в маніфесті для цього немає |
| Пакети npm | dependencies.npm в elide.pkl, потім elide install --ecosystems= |
| Пакети PyPI | Віртуальне середовище Python 3.13, вибране через VIRTUAL_ENV |
Налаштування проєкту
// elide.pkl
amends "elide:project.pkl"
name = "poly"
dependencies {
npm { packages { "pretty-ms@9.3.1" } }
pypi { packages { "humanize==4.12.3" } }
}elide install --ecosystems=npmelide install без параметрів встановлює лише Maven. Пакети PyPI Elide не встановлює:
elide install --ecosystems=pypi завершується з кодом 2 і повідомленням
pypi installs are not available in this build. Залиште блок pypi як запис про залежності й установіть пакети через
pip із Python 3.13 у віртуальне середовище:
python3.13 -m venv .venv
.venv/bin/pip install humanize==4.12.3
export VIRTUAL_ENV=$PWD/.venvElide завантажує пакети з $VIRTUAL_ENV/lib/python3.13/site-packages. Пакети на чистому Python працюють; деякі модулі
розширень на C не завантажуються (див. Python).
Написання програми
# report.py
import humanize
def size(n):
return humanize.naturalsize(n)
def summarize(files):
total = sum(f.bytes for f in files)
return {"count": len(files), "total": humanize.naturalsize(total)}// app.mjs
import prettyMs from "pretty-ms";
import report from "./report.py";
const files = [
{ name: "build.log", bytes: 1_500_000, ageMs: 172_800_000 },
{ name: "test.log", bytes: 32_000, ageMs: 5_400_000 },
];
for (const f of files) {
console.log(`${f.name}: ${report.size(f.bytes)}, ${prettyMs(f.ageMs)} old`);
}
const summary = report.summarize(files);
console.log(`${summary.count} files, ${summary.total}`);elide --interop run app.mjsbuild.log: 1.5 MB, 2d old
test.log: 32.0 kB, 1h 30m old
2 files, 1.5 MBЕкспорт за замовчуванням у файлі Python — це його модуль; імпортуйте його з точки входу .mjs. Дві поширені помилки:
| Чого бракує | Помилка |
|---|---|
--interop | Error: Cannot import 'report. |
VIRTUAL_ENV | ModuleNotFoundError: No module named 'humanize' |
Передавання значень
# shapes.py
def label(order):
return f"{order.item} x{order.qty}"
def doubled(prices):
return [p * 2 for p in prices]
def config():
return {"region": "eu", "retries": 3}
def apply(fn, value):
return fn(value)
def fail():
raise ValueError("bad input")// values.mjs
import shapes from "./shapes.py";
console.log(shapes.label({ item: "bolt", qty: 4 }));
console.log(shapes.doubled([1, 2.5, 3]).map((n) => n + 1));
const config = shapes.config();
console.log(config.region, config.get("retries"));
console.log(JSON.stringify(Object.fromEntries(config.items())));
console.log(shapes.apply((s) => s.toUpperCase(), "shout"));
console.log(shapes.apply((v) => v, null), shapes.apply((v) => v, undefined));elide --interop run values.mjsbolt x4
(3)[3, 6, 7]
eu 3
{"region":"eu","retries":3}
SHOUT
null undefined| Значення | З JavaScript у Python | З Python у JavaScript |
|---|---|---|
| Числа, рядки, булеві значення | Нативні значення | Нативні значення |
null, undefined / None | None, назад без змін | null |
Об’єкт / dict | Поля читаються як атрибути (order.item); order["item"] кидає TypeError | Ключі читаються як d.key, d["key"] або d.get("key"); Object.keys, in і JSON.stringify бачать методи словника, а не його ключі. Перетворюйте через Object.. |
Масив / list | Підтримує ітерацію та індексацію, len() працює | Array.isArray дорівнює true; map, spread і Array.from працюють |
| Функція | Можна викликати | Можна викликати |
Виклик JavaScript із Python
Модуль elide обчислює JavaScript і повертає його значення:
# calls.py
from elide import js
slug = js("(s) => s.trim().toLowerCase().replaceAll(' ', '-')")
print(slug(" Hello Polyglot World "))
point = js("({ x: 1, y: 2, tags: ['a', 'b'] })")
print(point.x + point.y, point.tags[0], len(point.tags))
print(sorted(js("[3, 1, 2]")))
try:
js("JSON.parse('{oops')")
except RuntimeError as e:
print("caught:", e)
js("Promise.resolve(42)").then(lambda v: print("resolved:", v))elide --interop python calls.pyhello-polyglot-world
3 a 2
[1, 2, 3]
caught: JSException: SyntaxError: Unexpected token o in JSON at position 1
resolved: 42Обробка помилок
Виняток Python надходить у JavaScript як Error, у якого name — клас винятку; помилка JavaScript надходить у Python
як RuntimeError. Неперехоплена помилка виводить один стек через обидві мови:
// errors.mjs
import shapes from "./shapes.py";
try {
shapes.fail();
} catch (e) {
console.log(e.name, "|", e.message);
}
shapes.apply((x) => {
throw new RangeError(`bad value ${x}`);
}, 7);elide --interop run errors.mjsValueError | ValueError: bad input
RangeError: bad value 7
at :=> (errors.mjs:10:9)
at apply (shapes.py:11:12)
at :module:eval (errors.mjs:9:1)Програма завершується з кодом 1.
Виклик асинхронного коду
| Звідки | Працює | Не працює |
|---|---|---|
| JavaScript викликає Python | Виклик синхронної обгортки, яка виконує asyncio.run(...) | await для корутини Python повертає саму корутину, не виконуючи її |
| Python тримає проміс JavaScript | promise.then(callback) | await promise кидає TypeError: object polyglot. |
# rates.py
import asyncio
async def fetch_rate(code):
await asyncio.sleep(0.01)
return {"EUR": 0.92, "GBP": 0.79}[code]
def rate(code):
return asyncio.run(fetch_rate(code))
def when_ready(promise, done):
promise.then(lambda value: done(f"python saw {value}"))// rates.mjs
import rates from "./rates.py";
console.log("rate:", rates.rate("EUR"));
const total = new Promise((resolve) => setTimeout(() => resolve(7), 10));
rates.when_ready(total, (msg) => console.log(msg));
await total;elide --interop run rates.mjsrate: 0.92
python saw 7asyncio.run блокує цикл подій JavaScript, доки корутина не завершиться. Потоки Python під --interop недоступні.
Java і Kotlin
elide run Hello.kt запускає Kotlin окремо; JavaScript і Python не можуть його викликати. Імпорт завершується
помилкою:
import hello from "./Hello.kt";TypeError: Unsupported file extension: 'file:/path/to/Hello.kt'Див. також Мови та взаємодія, Python і Встановлювач npm.