Перейти к содержанию

412 уроков, 25 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 19 из 20 Средний 15 мин 100 XP

Jython, IronPython, RustPython и Brython: Python на чужих платформах

Четыре реализации для четырёх сред: Python на JVM, на .NET, на Rust и прямо в браузере. Зачем их переписывали, что они умеют сегодня и чем Brython отличается от Pyodide из песочницы.

Редакция Питоники

CPython, PyPy и MicroPython закрыли вопросы скорости и размера. Остались две редкие, но показательные причины существовать для реализаций: платформа и среда. Четыре проекта этого урока отвечают на четыре вопроса: как исполнить Python там, где правит Java; где правит .NET; как встроить язык в чужие программы на Rust; и как исполнять его прямо в браузере без установки чего-либо.

Зачем переписывать Python под чужую платформу

Ответ один для Jython и IronPython: мост к библиотекам. Программы на Java и .NET держат гигантские экосистемы классов, и реализация Python поверх платформы позволяет дотягиваться до них прямо из Python-кода: Jython видит Java-классы как свои, IronPython — объекты .NET. Это делает Python языком скриптов для целых платформ: конфигурация, автоматизация, расширение чужих приложений. Сам язык при этом не меняется — и переносимость обычного кода стоит на месте:

обычный класс переносится всюду
class Account:
    def __init__(self, owner):
        self.owner = owner
        self.balance = 0

    def deposit(self, amount):
        self.balance = self.balance + amount
        return self.balance

acc = Account('Анна')
acc.deposit(100)
print('после второго взноса:', acc.deposit(50))
print(acc.owner, '-', acc.balance)
Вывод
после второго взноса: 150
Анна - 150

Этот класс поведёт себя одинаково на CPython, Jython и IronPython: классы, атрибуты, методы — часть языка. Различия начинаются на границе: то, что в Jython выглядит обычным объектом, может быть настоящим Java-классом, и у него появятся платформенные методы, которых нет у питон-объектов. Чистый Python-код без платформенных мостов переносится между реализациями: меняется среда, а не семантика языка.

Четыре реализации одним взглядом

РеализацияСредаСостояниеЗачем существует
JythonJVMВыпускается медленно, уровень Python 2Python-код поверх Java-классов
IronPython.NETЖивая линия Python 3, совместимость отстаёт от CPythonСкрипты внутри .NET-приложений
RustPythonВстраивание, WASMВ разработке, совместимость неполнаяВстраивать Python в Rust-проекты
BrythonБраузерАктивная разработкаPython-синтаксис вместо JavaScript над DOM

Статусы разные, и на них стоит смотреть трезво. Jython десятилетиями живёт на уровне Python 2 — современный код с f-строками там не запустится. IronPython добрался до линии Python 3, но отставание от CPython — в релизы: новые конструкции языка появляются с задержкой. RustPython — молодой проект: значительная часть языка работает, но полная совместимость ещё впереди, зато его удобно встраивать в программы на Rust и собирать в WebAssembly. Brython живёт в браузере: он переводит Python-код в JavaScript прямо на странице, без установки интерпретатора.

Как код узнаёт среду

Каждая реализация честно называет себя через sys.implementation: Jython — java, IronPython — cli, у RustPython — rust. Тот же каркас из урока 16 с переносимым словарём имён:

определение среды по имени реализации
import sys

NAMES = {
    'cpython': 'эталонная реализация на C',
    'pypy': 'PyPy: JIT на Python',
    'java': 'Jython на JVM',
    'cli': 'IronPython на .NET',
    'rust': 'RustPython на Rust',
}

impl = sys.implementation.name
print('здесь работает:', NAMES.get(impl, 'другая реализация'))
Вывод
здесь работает: эталонная реализация на C

В песочнице сработала запись для cpython; на настоящей Jython-машине словарь вернул бы значение про JVM. Метод get со значением по умолчанию — правильная манера для таких таблиц: неизвестная реализация не уронит код, а попадёт в запасную ветку. Brython в этот словарь тоже попадёт — он реализует sys.implementation со своим именем.

Отдельный вопрос — что из коллекций переезжает на платформы без потерь. Словари и сортировка — часть языка, и на любой из четырёх сред такой код работает одинаково:

коллекции переезжают без потерь
stock = {'tool': 5, 'box': 2}

for name, count in sorted(stock.items()):
    print(name, '-', count)
print('всего позиций:', len(stock))
Вывод
box - 2
tool - 5
всего позиций: 2

Brython: браузер как среда

Brython — самый необычный из четырёх: вместо интерпретатора под платформу он работает прямо в браузере. Страница подключает Brython, тот читает Python-код из тега с типом text/python, транслирует его в JavaScript и выполняет. DOM при этом доступен через модуль browser — проверим, что на обычном Python его нет:

browser есть только в браузере
try:
    from browser import document
    print('browser доступен: мы внутри Brython')
except ImportError:
    print('browser недоступен: обычный Python без DOM')
Вывод
browser недоступен: обычный Python без DOM

В песочнице ответ тот же, что и для machine из урока 18: модуль из чужой среды честно не импортируется. На странице с подключённым Brython первая ветка открылась бы, и document стал бы живым DOM-объектом, с которым Python-код меняет содержимое страницы:

Python-код внутри HTML-страницы с Brython
<script type='text/python'>
from browser import document
document <= 'Привет из Python'
</script>
Фрагмент HTML-страницы: выполняется браузером при подключённом Brython. В песочнице и на десктопе модуля browser нет — код приведён как иллюстрация среды.

Запись document <= текст — Brython-овская вставка содержимого в элемент: платформенные API приходят со своим синтаксисом. Это и есть цена моста: язык остаётся питоном, но граница со средой живёт по правилам среды.

Чем Brython отличается от Pyodide

На первый взгляд два способа исполнять Python в браузере — а на самом деле это противоположные подходы. Песочница этого сайта работает на Pyodide: это настоящий CPython, скомпилированный в WebAssembly — урок 16 показывал, что он честно отвечает cpython. Brython — не CPython: это отдельная реализация на JavaScript, и гарантии у неё другие:

СвойствоPyodideBrython
Что этоCPython в WebAssemblyРеализация Python на JavaScript
СовместимостьПолная CPython-совместимостьБольшая часть языка, свои ограничения
C-расширенияРаботают: пакеты скомпилированы под WASMНе поддерживаются
Доступ к DOMНет: это среда без браузерного DOMДа, через модуль browser
ВесМегабайты: везёт настоящий интерпретаторЛегче: транслятор вместо интерпретатора

Практический итог: для серьёзных вычислений и настоящих библиотек в браузере берут Pyodide — он несёт настоящий CPython и его пакеты; Brython выигрывает весом и прямотой к DOM — учебные страницы и простые веб-приложения на Python-синтаксисе. Для песочницы Питоники выбор очевиден: совместимость важнее, поэтому уроки компиляции исполняются на честном CPython.

Статус и выбор

  • Jython — если поддерживаете наследие с Java и Python 2-уровнем: современный код на него не нацеливают;
  • IronPython — если встраиваете скрипты в .NET-приложения: тот редкий случай, когда платформа важнее свежести языка;
  • RustPython — следить и экспериментировать: встраивание в Rust-проекты и WASM-сборки;
  • Brython — учебные страницы и лёгкие веб-приложения на Python-синтаксисе;
  • настоящий Python в браузере — чаще Pyodide: полный CPython с пакетами.
переносимый отчёт о среде
import sys

report = [
    'реализация: ' + sys.implementation.name,
    'версия языка не ниже 3.6: ' + str(sys.version_info >= (3, 6)),
    'байткод-машина: ' + str(hasattr(sys.implementation, 'cache_tag')),
]
for line in report:
    print(line)
Вывод
реализация: cpython
версия языка не ниже 3.6: True
байткод-машина: True

Три строки отчёта перенесутся на любую из четырёх реализаций без правок: имя вернётся своё, проверка версии отработает по-своему честно, а cache_tag есть у всех сред с байткод-кэшем. Это хороший тест переносимости: если отчёт о среде живёт — каркас программы переносим, различия будут только на платформенных границах.

Чистый Python-код без платформенных мостов переносится между реализациями: меняется среда, а не семантика языка. Jython и IronPython покупают мосты к Java и .NET ценой отставания, RustPython — встраиваемость ценой незавершённости, Brython — браузер ценой JavaScript-природы. Раздел о реализациях на этом закрыт, и впереди — финальный проект: собираем standalone-инструмент из исходника до проверенного архива.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

import sys
NAMES = {
    'cpython': 'эталон',
    'java': 'Jython',
    'cli': 'IronPython',
}
print(NAMES.get(sys.implementation.name, 'неизвестно'))
try:
    from browser import document
    print('есть DOM')
except ImportError:
    print('нет DOM')
class Point:
    def __init__(self, x):
        self.x = x

    def double(self):
        return self.x * 2

p = Point(21)
print(p.double())
Проверь себя
0 / 7

1. Зачем существуют Jython и IronPython?

2. Какое имя возвращает sys.implementation.name на Jython?

3. На каком уровне языка находится современный Jython?

4. Что делает Brython со страницей?

5. Чем Pyodide отличается от Brython?

6. Заработает ли numpy через C API на RustPython?

7. Что означает hasattr(sys.implementation, 'cache_tag') == True?

Карточки терминов
Запомнено: 0 / 7
Практика

Напишите функцию platform_label(), которая по имени реализации возвращает эталон для cpython и альтернатива для любого другого имени. Напечатайте имя текущей среды и её роль.

practice.py
Вопросы и ответы по уроку

Что такое Jython и жив ли он?

Jython — реализация Python на JVM с прямым доступом к Java-классам. Он жив, но остался на уровне Python 2: для нового кода его не выбирают, только для поддержки старых систем на Java.

Чем IronPython отличается от CPython?

IronPython исполняет Python поверх .NET: его сила — прямой доступ к объектам .NET и встраивание скриптов в приложения на этой платформе. Языковая совместимость отстаёт от CPython на релизы, а C-расширения не работают.

Урок 16: реализации Python

Можно ли писать веб-страницы на Python через Brython?

Да: страница подключает Brython, и Python-код из тега text/python выполняется в браузере, меняя DOM через модуль browser. Для больших проектов чаще берут Pyodide — настоящий CPython в WebAssembly.

Что такое RustPython и готов ли он к работе?

Это встраиваемая реализация Python на Rust. Значительная часть языка уже работает, но полная совместимость ещё в разработке. Ценность — встраивание Python в Rust-проекты и сборки под WebAssembly.

Какой код переносится между всеми этими реализациями?

Чистый Python без платформенных мостов: классы, словари, сортировка, стандартные алгоритмы. Непереносимы C-расширения и опора на новейший синтаксис — альтернативы отстают от CPython по версиям.

Понравился урок? Сошлитесь на него

«Чистый Python-код без платформенных мостов переносится между реализациями: меняется среда, а не семантика языка.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.