Python ↔ JavaScript
Cloudflare Workers + Python
Заголовок раздела «Cloudflare Workers + Python»Cloudflare Workers исполняют JavaScript/WebAssembly на edge-серверах. Python-код работает через Pyodide — CPython, скомпилированный в WebAssembly. Cloudflare предоставляет интеграцию через compatibility_flags = ["python_workers"].
Граница Python ↔ JS
Заголовок раздела «Граница Python ↔ JS»В Workers Python и JavaScript сосуществуют в одном рантайме. Pyodide автоматически оборачивает JS-объекты в JsProxy, но некоторые API требуют конвертации.
Проблема: Map vs Object
Заголовок раздела «Проблема: Map vs Object»Pyodide по умолчанию конвертирует Python dict в JS Map. Но API Cloudflare (KV, D1, R2) ожидают обычный Object:
# ❌ Не работает — Map вместо Objectfrom pyodide.ffi import to_jsoptions = to_js({"expirationTtl": 3600})await env.KV.put("key", "value", options) # Error!
# ✅ Работает — Objectfrom edgebot import to_js_objectoptions = to_js_object({"expirationTtl": 3600})await env.KV.put("key", "value", options) # OKto_js_object использует Object.fromEntries для конвертации:
from pyodide.ffi import to_jsfrom js import Object
def to_js_object(value): return to_js(value, dict_converter=Object.fromEntries)Проблема: JS null/undefined
Заголовок раздела «Проблема: JS null/undefined»JS имеет два «пустых» значения: null и undefined. В Pyodide они представлены как JsNull и JsUndefined — это не Python None:
value = await env.KV.get("missing_key")# value — это JsNull, не None!# value is None → False# value == None → может вернуть True, может нетto_py нормализует nullish-значения:
from edgebot import to_py
value = to_py(await env.KV.get("missing_key"))# value is None → True ✓Что инкапсулирует SDK
Заголовок раздела «Что инкапсулирует SDK»| Задача | Без SDK | С SDK |
|---|---|---|
| Dict → JS Object | to_js(d, dict_converter=Object.fromEntries) | to_js_object(d) |
| JS null → None | Проверка type(v).__name__ | to_py(v) |
| HTTP fetch | await js_fetch(url, options) | await fetch(url, options) (+ ретраи) |
| Пауза | await Promise.new(lambda r,_: setTimeout(…)) | await sleep(1000) |
| console.* | js.console.info(msg) | log.info(msg, source=...) |
Ограничения Pyodide в Workers
Заголовок раздела «Ограничения Pyodide в Workers»- Нет файловой системы —
open()не работает - Нет subprocess — нельзя запускать внешние процессы
- Нет threading — только async/await
- Ограниченные пакеты — только чистый Python (без C-расширений), либо пакеты из Pyodide packages
- CPU-лимит — 10ms (бесплатный план) или 30s (платный) на запрос
- Размер бандла — до 10 MB
Как используется fetch
Заголовок раздела «Как используется fetch»SDK оборачивает js.fetch в edgebot.utils.http.fetch с:
- Автоматическими ретраями при 408, 429, 5xx
- Уважением заголовка
Retry-Afterдля 429 - Логированием попыток
Все вызовы Telegram API (send_message, edit_message_text и т.д.) проходят через эту обёртку.