«Подождите, что?» — вот как, по моему мнению, большинство людей отреагирует на название этой статьи.
Что вы имеете в виду, говоря «Просто используйте браузерный Python»?
Все знают, что браузеры могут выполнять только JavaScript.
Ниже приведен скриншот исходного кода моего личного сайта, посмотрите, заметите ли вы что-то другое:
Да, это Python!
А теперь давайте поговорим о том, как это работает, насколько хорошо это работает, и какие еще альтернативы браузерному JS существуют.
Представляем Brython
Brython — это реализация Python3, написанная на JavaScript, которая позволяет писать Python-код для веб.
По сути, это библиотека JavaScript, которая преобразует ваш Python-код в эквивалентный JS и обрабатывает его во время выполнения.
И поскольку написание Python для браузера звучит довольно круто, я решил попробовать.
Создаем игру Змейка с помощью Brython

Вот ссылка на мой сайт, где вы можете попробовать как JavaScript, так и Brython Snake. А вот ссылка на весь код на GitHub.
Для того чтобы попробовать Brython в действии, я решил создать классическую игру «Змейка».
Поскольку я не специалист по HTML Canvas и не разработчик игр, я решил использовать эту реализацию JavaScript в качестве отправной точки. Я уже создавал свою собственную игру-змейку на холсте, но эта намного аккуратнее и компактнее.
О да, и этот парень создал ее менее чем за 5 минут. Спасибо Крису Делеону, это очень впечатляет.
Итак, в дополнение к реализации Криса я добавил функцию подсчета очков и результатов, немного улучшил интерфейс, добавил кнопку паузы и кнопку инструкций. Затем я портировал его на Brython.
На самом деле, я также изменил его код так, чтобы он работал в строгом режиме JS, поскольку он использовал такие вещи, как неявные глобалы, которые, как мне кажется, не являются репрезентативными для большинства JavaScript (не критикую его — он занимался скоростным кодированием), и я хотел получить хорошее сравнение кода Brython и JS.
В итоге JavaScript получился таким, и я не буду публиковать здесь этот фрагмент, потому что моя цель — сосредоточиться на Brython.
Хотя большая часть кода Brython была «прямым переводом» JS, некоторые части, например, функциональность подсчета очков, я создал непосредственно в Brython, а затем реализовал в JS, чтобы посмотреть, как это будет выглядеть.
Конечный результат таков:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Brython Snake</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js">
</script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<style> /* Removed to keep the snippet short. Find the full file here: */ </style>
</head>
<body onload="brython()">
<h1 class="text-center">Snake built with <a href="https://brython.info">Python!</a></h1>
<canvas id="game-board" width="400" height="400"></canvas>
<br>
<h3 id="score" class="text-center">Score: 0</h3>
<br>
<h6 id="high-score" class="text-center">High Score: 0</h6>
<br>
<div class="text-center">
<button id="instructions-btn" class="btn btn-info">Instructions</button>
</div>
<script type="text/python">
from browser import document, html, window
from javascript import Math
score = 0
high_score = 0
px = py = 10
gs = tc = 20
ax = ay = 15
xv = yv = 0
trail = []
tail = 5
pre_pause = [0,0]
paused = False
def game():
global px, py, tc, gs, ax, ay, trail, tail, score
px += xv
py += yv
if px < 0:
px = tc-1
if px > tc-1:
px = 0
if py < 0:
py = tc-1
if py > tc-1:
py = 0
ctx.fillStyle = "black"
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = "lime"
for i in range(len(trail)):
ctx.fillRect(trail[i][0]*gs, trail[i][1]*gs, gs-2, gs-2)
if trail[i][0] == px and trail[i][1] == py:
score = score if paused else 0
tail = 5
trail.insert(0, [px, py])
while len(trail) > tail:
trail.pop()
if ax == px and ay == py:
tail += 1
ax = Math.floor(Math.random()*tc)
ay = Math.floor(Math.random()*tc)
score += 1
update_score(score)
ctx.fillStyle = "red"
ctx.fillRect(ax*gs, ay*gs, gs-2, gs-2)
def update_score(new_score):
global high_score
document["score"].innerHTML = "Score: " + str(new_score)
if new_score > high_score:
document["high-score"].innerHTML = "High Score: " + str(new_score)
high_score = new_score
def key_push(evt):
global xv, yv, pre_pause, paused
key = evt.keyCode
if key == 37 and not paused:
xv = -1
yv = 0
elif key == 38 and not paused:
xv = 0
yv = -1
elif key == 39 and not paused:
xv = 1
yv = 0
elif key == 40 and not paused:
xv = 0
yv = 1
elif key == 32:
temp = [xv, yv]
xv = pre_pause[0]
yv = pre_pause[1]
pre_pause = [*temp]
paused = not paused
def show_instructions(evt):
window.alert("Use the arrow keys to move and press spacebar to pause the game.")
canvas = document["game-board"]
ctx = canvas.getContext("2d")
document.addEventListener("keydown", key_push)
game_loop = window.setInterval(game, 1000/15)
instructions_btn = document["instructions-btn"]
instructions_btn.addEventListener("click", show_instructions)
</script>
</body>
</html>
Итак, основываясь на этом фрагменте, давайте разберем некоторые ключевые понятия о Brython:
Включая brython.js
Для Brython не требуется установка. Просто импортируйте скрипт внутри <head> :
<script type=”text/javascript” src=”https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js">
Запуск Brython
Для того, чтобы Brython мог транслировать и исполнять код на Python как обычный JS, нам нужно вызвать brython сразу после загрузки тела документа, как показано ниже:
<body onload=”brython()”>
Он будет искать теги сценариев типа text/python и оценивать код внутри них.
API для работы с Веб
По умолчанию JavaScript предоставляет вам доступ к таким объектам, как документ и окно, которые необходимы в любом проекте JS. Таким образом, Brython должен иметь способ включить и их.
Чтобы решить эту проблему, создатели Brython могли бы просто позволить разработчикам по умолчанию сразу обращаться к document и window в коде Python, но это заставило бы отладчики Python постоянно кричать о undefined variable и ухудшило бы производительность.
Таким образом, чтобы использовать эти Web API, мы должны импортировать их так же, как мы это делаем с любым модулем Python:
from browser import document, html, window
На самом деле, вам не нужно выполнять pip install . В конце концов, мы вставляем это в наш HTML! Просто включите операторы импорта, и все в порядке — Brython будет знать, что делать.
Чтобы проверить, насколько хорошо это работает, я попробовал несколько различных методов из Web API, таких как alert , setInterval , addEventListener и т.д. Все сработало, как и ожидалось.
Объекты и методы нативного JavaScript
В игре Snake, после того как змея съест яблоко, нам нужно сгенерировать новое яблоко в случайном месте.
Однако, когда я начинал работать с Brython, я не знал, что могу использовать модуль случайных чисел random Python (вы можете!). Как же мне сгенерировать случайное число (без создания собственной библиотеки)?
Оказывается, на самом деле мы можем получить доступ к большему количеству JavaScript, чем я думал. Посмотрите на это:
from javascript import Math random_num = Math.floor(Math.random()*10)
С модулем javascript, если есть объект, к которому я могу обратиться с помощью JS, я могу обратиться к нему с помощью Brython.
Например, если я импортирую библиотеку JavaScript (jQuery, Bootstrap) и хочу использовать ее методы — я могу сделать это с помощью from javascript import <library>. И, естественно, таким же образом я могу использовать встроенные объекты JS, такие как Date или String .
Концепции, специфичные для конкретного языка
В Python, если я хочу распаковать список, я могу сделать list2 = [*list1] . Также, если я хочу установить значение переменной на основе условия, я использую foo = 10 if condition else 20.
These do have JavaScript equivalents: the spread operator( [...arr] ) and the ternary operator ( let foo = condition ? 10 : 20 ).
У них есть эквиваленты в JavaScript: оператор spread( [...arr] ) и троичный оператор ( let foo = condition ? 10 : 20 ).
Но поддерживает ли их Brython?
Я попробовал их использовать, и все работает отлично. Вы увидите, что распаковка списка Python и условное присвоение включены в мой окончательный исходный код.
Отладка
Честно говоря, я думал, что отладка Brython будет ужасной.
Однако на самом деле все не так уж плохо.
Конечно, то, что я создал, это небольшой проект, не очень сложный, но ошибки, выдаваемые Brython, были в основном точными и достаточно описательными.
Это верно, по крайней мере, в отношении проблем с синтаксисом. Импорт модулей Python — это совсем другое дело.
Производительность


Как и ожидалось, оценка кода Brython во время выполнения выполняется медленнее, чем JavaScript. В моем случае это было примерно в 1,7 раза медленнее.
Для более сложных проектов, я подозреваю, Brython будет в несколько раз медленнее, чем чистый JS.
Однако вы можете заранее транспонировать код Brython и включать JavaScript только на веб-странице, что должно улучшить работу.
Я пытался использовать редактор Brython Editor для преобразования кода Brython в JS и запуска реального JS на веб-странице, но он выдавал так много ошибок, что я решил пока отложить его в сторону. Впрочем, я не приложил к этому много усилий.
Заключительные размышления о Brython
Честно говоря, Brython произвел на меня большое впечатление. Вот некоторые плюсы и минусы из моего собственного опыта работы с этим языком:
Плюсы
- Мне удалось написать «Змейку» без лишних хлопот, причем опыт отладки оказался на удивление положительным.
- В моем простом проекте Brython беспрепятственно взаимодействовал с нативными JavaScript-объектами, доступными на странице
- Я ценю тот факт, что мой код выглядит чище на Python, а также мне нравится, что я могу использовать полезные конструкции из Python для написания браузерного кода.
- В случае с моей игрой, хоть Brython загружается медленнее, чем JavaScript, пользователь этой разницы не замечает.
- Мне приятно видеть Python в исходном коде моего сайта.
Минусы
- Брайтон работает значительно медленнее, чем чистый JS.
- Для использования Brython разработчику необходимо иметь опыт работы с JavaScript.
- Вы неизбежно столкнетесь с большим количеством ошибок
- Документации Brython и его сайту есть куда расти в плане удобства навигации и возможностей обучения
- У Brython отсутствует сильная экосистема и инструменты развития.
В целом, закончив свой первый проект с Brython, я могу с уверенностью сказать, что когда-нибудь попробую его снова.
Однако я считаю, что в нынешнем виде Brython больше подходит для разработчиков JavaScript, которые знают Python и устали от JavaScript, чем для разработчиков Python, которые хотят заниматься веб-разработкой без необходимости изучать JavaScript.
Чтобы хорошо работать с Brython, я думаю, вам нужно немного понимать JavaScript. И если вы решите потратить время на изучение достаточного количества JavaScript, чтобы с легкостью писать на Brython, то с тем же успехом вы можете просто использовать JavaScript.
Другие альтернативы Browser JS

Причина, по которой я выбрал Brython, заключается в том, что из всех альтернатив Python to JS, о которых я впервые узнал, это был единственный, который все еще активно разрабатывался на GitHub. Большинство транспилеров Python → JavaScript, с которыми я сталкивался, вообще не видели коммитов за последние несколько лет.
Однако существуют и другие альтернативы.
Например, интересным представляется Pyodide. Он компилирует Python (вместе с его научными библиотеками) в WebAssembly, что позволяет запускать его в браузере.
WebAssembly, как следует из названия, — это язык ассемблера для веба (Интернета). Подобно тому, как ассемблер в наших компьютерах может работать как посредник между языками высокого уровня и машинным кодом, WebAssembly может позволить то же самое сделать в Интернете.
Таким образом, можно написать компилятор для Python или любого другого языка к WebAssembly, что позволит запускать его в браузере.
Это амбициозный и многообещающий проект, который, вероятно, приведет к тому, что мы будем видеть все больше и больше веб-разработок без JavaScript.
Однако он все еще находится в зачаточном состоянии (~3 года), поэтому, вероятно, пройдет некоторое время, прежде чем мы увидим, как JavaScript будет заменен другими языками на регулярной основе.
А пока этого не происходит, вам придется прибегнуть к таким инструментам, как Brython, если вы действительно не можете работать с JavaScript.
Но, честно говоря, это неплохое начало!




















