Brython: заменяем JavaScript на Python на фронтенде

Автор оригинала: Rajiv Abraham
  • Перевод
Привет, Хабр!

К огромному удовлетворению нашей читательской аудитории, наша работа над обновлением книг по Python не прекращается. Но не прекращается и поиск в этом направлении — и сегодня мы хотели бы упомянуть Brython — Python для браузеров. Статья короткая, немного игривая и детективная, мы постарались сохранить авторский стиль.

В этой статье дается краткое введение в работу с Brython, реализацией Python для разработки на фронтенде (в браузере).

Весь проект выложен здесь.

Введение


Завидуя успеху программистов JavaScript, питонисты-заговорщики тайно встретились, чтобы обсудить будущее Python в этом апокалиптическом мире. Повсюду JavaScript, отжирающий поляну у Python. Вооружившись Node.js, язык JavaScript вторгся на территорию Python, и тот утратил свою доминирующую роль всеми любимого серверного языка, где ранее соперничал с Ruby (помните те времена?). Тогда пришло время сделать вылазку в самое сердце территории JavaScript: в браузер.

Не забывайте вашу историю (и помните о будущем)


Эта дилемма волновала не только вышеупомянутых заговорщиков. Был еще один рыцарь плаща и кинжала, автор Transcrypt. Он решил написать компилятор для Python, компилирующий код прямо в JavaScript Как хороший отравитель, он не оставлял после себя и следа Python. Выглядело это многообещающе.

Другие предпочитали воспользоваться уроками истории. Просто иммигрировать всей семьей. По крайней мере, именно так мыслили создатели Pyodide. Они собирались создать на стороне JavaScript анклав с полноценным интерпретатором Python, который мог бы выполнять код на Python. Соответственно, там можно было гонять любой код Python, в том числе, большую часть его стека для data science, где есть привязки к языку C (например, Numpy, Pandas).

Это также выглядит очень многообещающе. Но первичные ленивые тесты, проведенные автором Pyodide, показали, что поначалу страница грузилась немного медленно.

Тогда заговорщики поступили именно в духе хороших заговорщиков: создали другой компилятор для преобразования Python в JavaScript, но на этот раз выполнять компиляцию в JavaScript при загрузке страницы (а не как Transcrypt, компилирующий код в JavaScript заранее). Так сформировалось Братство Brython. Одна змея, чтоб править ими всеми.

Hello World


Давайте напишем традиционный ‘Hello World’

А вот и десант Brython (это я о компиляторе).

<script type="text/javascript"
       src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js">
</script>
Активируем его при загрузке страницы
<body onload="brython()">
...
</body>

В теге body, показанном выше, мы пишем код на Brython:

<script type="text/python">
from browser import document

document <= "Hello World"
</script>

Просто добавляем Hello World в элемент document. Хм. Очень легко.

В полном виде — ниже.

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <script type="text/javascript"
        src="https://cdn.jsdelivr.net/npm/brython@3.8.8/brython.min.js">
    </script>
</head>

<body onload="brython()">

<script type="text/python">
from browser import document

document <= "Hello World"
</script>
</body>
</html>

В таком случае на страницу будет просто выведено приветствие “Hello World”.

Калькулятор


Давайте напишем калькулятор на Brython. Весь его код выложен здесь.



Да, вы догадались, нам понадобится таблица. Давайте ее сделаем.

from browser import document, html
calc = html.TABLE()

Добавим только первый ряд. То есть отобразим поле для чисел (назовем его result) и клавишу C.

calc <= html.TR(html.TH(html.DIV("0", id="result"), colspan=3) +
                html.TD("C"))

Да, я тоже не слишком уверен в этом синтаксисе с <=. Но, посудите сами, такая классная библиотека, так что я и на него согласен.

Теперь добавим клавиатуру

lines = ["789/", "456*", "123-", "0.=+"]
calc <= (html.TR(html.TD(x) for x in line) for line in lines)

Наконец, добавим calc в document.

document <= calc

Итак, пока все хорошо. Как же нам добиться, чтобы все это работало? Сначала нужно захватить ссылку на элемент result, чтобы управлять им, когда будут нажиматься клавиши.

result = document["result"] # прямой доступ к элементу по его id

Далее нам потребуется обновлять result всякий раз, когда будет нажат любой элемент на клавиатуре. Для этого давайте сделаем обработчик событий. Доверимся разработчикам Brython и сочтем, что этот код работает. Обратите внимание на манипуляции с result в зависимости от того, какую кнопку вы нажали.

def action(event):
    """обрабатывает событие "click" при нажатии на кнопку калькулятора."""
    # Элементу, нажатому пользователем, соответствует атрибут "target" 
    # объекта event 
    element = event.target
    # Текст, выводимый на кнопке, записывается в атрибуте "text" элемента
    value = element.text
    if value not in "=C":
        # обновляем поле с результатом
        if result.text in ["0", "error"]:
            result.text = value
        else:
            result.text = result.text + value
    elif value == "C":
        # сброс
        result.text = "0"
    elif value == "=":
        # выполняем формулу в поле с результатом
        try:
            result.text = eval(result.text)
        except:
            result.text = "error"

Наконец, связываем вышеописанный обработчик событий с событием click на всех кнопках.

for button in document.select("td"):
    button.bind("click", action)

Видите как все было просто. Но, если серьезно, Brython кажется мне шедевром инженерной работы и, пожалуй, наилучшей иллюстрацией любви к языку Python. Пожалуйста, поддержите разработчиков и поставьте им звездочку в репозитории на Github!

Комментарии 8

    +6
    JavaScript вторгся на территорию Python, и тот утратил свою доминирующую роль всеми любимого серверного языка

    А точно ли Python был доминирующим серверным языком? У меня что-то огромные подозрения, что условный PHP не согласится с этим утверждением.
      –2
      Посмотрите на утилиты linux — perl, python. А вот php — не завезли :)
        +2
        Для меня оригинальный текст звучит как «Вот раньше сайтики и прочие сетевые самописные штуки были на Питоне в основном, а потом пришёл ЖС — и всё поменялось».
        Но если вы про утилиты говорите: так в линукс-среде и сейчас мало JS для всяких CLIшек/утилит/скриптов. Там как были C/C++ с налётом Perl/Python, так и сейчас, разве что Python 2 сменился на Python3, да всякий Go стал появляться изредка. Ну и на Perl сильно меньше пишут всяких скриптов, (хотя он всё ещё много где в зависимостях стоит).
      0
      статья классная, но один вопрос — зачем? С тайпскриптом-то понятно, он добавляет строгую типизацию со всеми вытекающими, но замена джаваскрита на пайтон, это как менять шило на мыло, ящитаю. А так прикольно
        +1

        В питоне строгая типизация. Если нужна статическая, то есть typing.

          –1

          Тайпинги не добавляют статической типизации в язык. Это всего лишь подсказки для линтеров и чекеров. Попробуйте определить тайпинг для переменной и записать туда значение другого типа. Питон и глазом не моргнет. И попробуйте то же самое проделать в java. Это и есть статическая типизация. А в питоне просто подсказки для инструментов, сам интерпретатор никак это не проверяет при выполнении

            0

            Да, добавляет типизацию только на этапе разработки. И если mypy или другой typing-линтер встроен в процесс сборки программы, то можно сказать, что программа статически проверена с точки зрения использования типов. В той же java можно написать код с использованием кастов, который скомпилируется, но упадет в рантайме. В C# дополнительно можно использовать dynamic, и что это меняет?

          0

          Согласен. По сути единственной серьезной претензией к js на фронте было отсутствие типизации, ts эту проблему решил. Скорость выполнения? Ну это точно не про сабж.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое