PyJamas: питон компилируемый в JS
2009-06-02 23:08Некоторое время назад появился интересный проект PyJamas. PyJamas - это компилятор питона в javascript, благодаря которому можно написать клиентскую часть приложения на питоне, скомпилировать его, и полученная подборка HTML,CSS и JS будет работать в любом браузере, понимающем JavaScript.
PyJamas: питон компилируемый в JS
PyJamas - это средство, позволяющее веб-программисту писать страницы на любимом языке программирования (python), компилировать их в JavaScript и запускать его в любом современном браузере (Mozilla, Old Mozilla (Netscape), IE, Safari and Opera) не задумываясь о совместимости.
Приложения на PyJamas
PyJamas выполняет компиляцию Python в JavaScript, поэтому питонисту при создании приложения для PyJamas требуется знаний HTML/CSS/JS не больше, чем программисту на C - знания ассемблера. Возможность писать непосредственно JS существует, но обычно без нее можно обойтись. PyJamas предоставляет библиотеку классов, позволяющую задать внешний вид и поведение пользовательского интерфейса созданием экземпляров классов и заданием их свойств, связей и методов. Такая реализация библиотеки сходна с традиционными библиотеками GUI.
Рассмотрим пример реализации простого пользовательского интерфейса:
from pyjamas.ui.SimplePanel import SimplePanel
from pyjamas.ui.VerticalPanel import VerticalPanel
from labeledpanel import LabeledPanel
class Statistic(SimplePanel) :
def __init__(self,query,count,engrank,rusrank) :
SimplePanel.__init__(self)
v = VerticalPanel()
v.setWidth("100%")
v.setBorderWidth("1px")
v.add(LabeledPanel("Оценка, английский:",engrank))
v.add(LabeledPanel("Оценка, русский:",rusrank))
v.add(LabeledPanel("Предъявлений:",count))
v.add(LabeledPanel("Длина выборки:",query))
self.add(v)
Здесь используется элемент оформления VerticalPanel, в который добавляются четыре элемента вывода LabeledPanel, снабженных названием и переменной. При запуске приложения появится панель, разделенная на четыре строки, в каждой из которых выводится название и значение переменной:

Каждый раз, когда переменной будет присваиваться значение, оно будет отображается в соответствующем поле интерфейса.
Такой код похож на программирование генератора кода для веб при помощи специальных библиотек. Само по себе это не ново и известно, как минимум, начиная с perl::CGI, а уж в zope.app.form и в zope.interface имеет более чем совершенный вид. PyJamas позволяет вместо многослойных разрозненных кодов на HTML/CSS/JS писать код на Python, это удобно, но элемент новизны и главное достоинство в том, что PyJamas не библиотека, а компилятор. Поэтому не только декларации элементов веб-интерфейса, но и сложное поведение веб-приложения, вычисления и обработку данных в нем можно реализовать используя развитые средства программирования языка Python, а не куцые конструкции на плохопереносимом JavaScript.
В качестве примера, посмотрим фрагмент кода, реализующий алгоритм смешения очереди:
class Sample :
# Пропущен некий код
def shuffle(self) :
key,translate,weight = self.q[0]
del self.q[0]
idx = int(random()*weight + 1)
if idx <= len(self.q) :
self.q.insert(idx,[key,translate,weight])
else :
self.farq.append([key,translate,weight])
if len(self.q) == 0:
self.sync()
self.q = self.farq
self.farq = []
Это привычный питоновский код, работающий с разными типами данных и использующий разные операторы, классы и после компиляции он работает в любом браузере, понимающим JS.
Приложения на PyJamas грузятся в браузер и работают в нем, благодаря этому на сайте PyJamas [2] представлены работающие примеры приложения и приведен их код.
PyJamas не ограничивается созданием приложений, работающих в браузере, а имеет расширение, PyJamas-Desktop [5], позволяющее запускать их как самостоятельные десктопные приложения, без какого-либо браузера.
Одностраничное приложение
Среди примеров [2] можно увидеть веб-приложение, реализующее почтовый клиент, напоминающий обычные IMAP-клиенты:

Конечно, таких продвинутых веб-интерфейсов, совсем не похожих на HTML-странички, можно было добиться и раньше, даже на голом HTML. Но PyJamas ориентирован на создание "одностраничных приложений". Такое приложение полностью загружается при первом обращении к странице вместе со всеми элементами оформления, а нажатие на кнопки и ссылки вызывает только загрузку дополнительных данных (не обязательно полностью оформленных страниц) или вообще оффлайновую обработку. Такое приложение, в сущности, клиент специального сетевого сервиса, взаимодействующего с ним поверх HTTP.
Наиболее часто приложения на PyJamas использует следующие способы взаимодействия с сервером:
- Чтение статических данных (страниц);
- Вызов удаленных процедур посредством JSONRPC (или XMLRPC);
Пример приложения, работающего со статическими данными, можно посмотреть на сайте PyJamas: это BookReader - приложение, позволяющего читать PyJamas Book. PyJamas Book написана на простом варианте структурированого текста и не содержит ни строчки HTML-разметки. BookReader загружает индекс страниц, а затем, по мере надобности, и сами страницы, выполняя разметку и отображение уже на стороне клиента. Такой подход позволяет создать интерактивный сайт на самом дешевом хостинге. вообще без какого-либо движка.
А вот использование JSONRPC требуют специальным образом написанной серверной части, но существует много готовых библиотек ([8], [9], [10]), чтобы ее реализовать.
Опыт использования
Недавно мне потребовалось написать на JS несложное приложение. Несколько дней ушло на борьбу за совместимость с разными браузерами и измышления такого алгоритма работы, который уложился бы в возможности этого языка без серьезных проблем. Получилось убого выглядящее, хотя и прилично работающее приложение:

Оно работает во "всех браузерах", правда, я не проверял его под Safari.
Бета-тестеры тут же запросили кучу возможностей, мысли о реализации которых вызвали уныние. В этот момент мне попалась на глаза очередная победная статья о PyJamas и я решил написать с его использованием альтернативную реализацию приложения. Всего через несколько часов получилось приложение с более развитым интерфейсом и более продвинутым алгоритмом работы:

Основной проблемой было изучение отсутствующей документации и легкую несовместимость python & pyjamas (об этом ниже). Несколько часов против нескольких дней это уже ощутимый выигрыш, да и добавление меню и трех форм тоску больше не навевает. А, кроме того, оно должно работать на Safari.
Основное ощутимое преимущество PyJamas не легкость написания интерфейса и переносимость между браузерами, а привычный и достаточно мощный язык программирования, позволивший реализовать более совершенные алгоритмы (даже несмотря на то, что из-за отсутствия random в PyJamas пришлось использовать конгруэнтный линейный генератор).
Плюсы и минусы
Даже при небольшом опыте программирования на PyJamas становится ясно, что это не питон, а его подмножество: не все конструкции питона работают, а другие работают не совсем корректно. Изучение кода PyJamas показало, что существенное улучшение совместимости - вопрос времени. Тем, кто решит попробовать писать на pyjamas, будет полезен список заметных проблем:
- Не все встроенные функции (map, zip, reduce, filter) есть и корректно работают;
- Не доступны библиотеки питона :), в том числе такие, которые могли бы существовать: random, regexp (их можно отобразить на JS);
- Странности с видимостью глобальных имен, которые не всегда оказываются видны;
- Легкая несовместимость в поведении классов (скажем, перекрыть __setattr__ мне не удалось);
- Имеет место несоответствие типов, что заметно даже для int.
Несмотря на это, код для PyJamas пишется так же легко, как обычные программы на питоне, что дает возможность легко реализовывать достаточно нетривиальные алгоритмы на стороне клиента.
Что касается предлагаемых PyJamas элементов пользовательского интерфейса и манеры его написания - то это, конечно, некий прорыв по сравнению с тем, что приходится переносить при реализации на чистом HTML/CSS. Тем не менее, если сравнивать с другими инструментами генерации веб-интерфейсов, такими как zope.app.form или ZPT, то придется отметить, что жесткое кодирования веб-интерфейса внутри кода приложения - это ощутимый шаг назад. Даже возможность раскрасить этот интерфейс при помощи CSS не приносит особой пользы: PyJamas использует табличный стиль верстки, в котором CSS не слишком спасает. Сравнение PyJamas с другими библиотеками GUI также неоднозначно: авторы напирают на преимущество HTML-ориентированности PyJamas, и сравнивают его с PyQT. Я не видел PyQT. Но если сравнить с Tck/Tk (это мой любимый GUI), то модель отображения HTML/CSS вообще недостойна упоминания, и, PyJamas не дает в этом смысле особых улучшений.
Значение
Веб начал свое развитие со статического HTML, который был интуитивно понятен новичкам и смог быстро распространится. Дальнейшее развитие привело к динамическим страницам, создаваемым под нужды индивидуального пользователя. По мере того, как алгоритмы динамической адаптации контента развивались, требовались все более мощные вычислительные сервера и все более толстые каналы связи. Постепенно появлялись специальные решения - сервера приложений и системы управления контентом на их основе - решающие распространенные задачи стандартным способом. Каждое из таких решений (Plone, Wordpress, Joomla или даже моя собственная CMS DreamBot) используется на множестве сайтов, отличие между которыми - только скин, тонкая прослойка графического представления, созданная под конкретный сайт. Все программное взаимодействие внутри сайта идентично для всех сайтов, сделанных на основе одной системы: скины можно переставлять между разными сайтами. Но не смотря на такую свободу, выбор скина всегда остается за владельцем сайта.

В тоже самое время наблюдалась и иная тенденция развития: чем более сложными и нагруженными становились сервера, чем большая толщина канала требовалось для быстрого отклика пользовательских приложений, тем большую часть вычислений пытались перенести с сервера на клиент. Основной способ добиться этого - создание HTML cо встроенными обработчиками событий, реализованных на JS. Его развитие в конце концов и привело к концепции "одностраничного приложения", которое загружает контент с сервера по мере надобности. PyJamas отражает и развивает эту тенденцию, делая еще один почти незаметный шаг: одностраничное приложение пишется не на каком-то специализированном языке специально обученным программистом, а на языке общего назначения с использованием среды, понятной люблому прикладнику, пишущему десктопные приложения.
И в этот момент происходит прыжок в будущее: появляется PyJamas-Desktop [5], который позволяет не только написать веб-интерфейс как десктопное приложение, но и использовать его так же: вне какого-либо браузера, как обычный клиент сетевого сервиса.
Как было сказано выше, протокол взаимодействия внутри любой CMS (или иной веб-службы) стандартизован в достаточной степени для свободной смены скина (или слоя представления). Если роль слоя представления отводится одностраничному приложению, написанному на PyJamas, то стоит пересобрать его с PyJamas-Desktop и превратить в десктопное приложение, как уже пользователи сайтов будут выбирать более удобный "скин" для работы. Если такое шаг будет сделан, то это действительно переворот в веб-технологиях: владелец сайта лишается возможности и потребности быть капризным ребенком, изобретающим "более представительный скин", приводящий в ступор посетителей. Посетитель будет сам выбирать более удобный и привычный веб-интерфейс для работы с сетевым сервисом: в сущности, это действительно его право и потребность.
А владельцам сайтов лучше озаботится качеством предоставляемого контента и возможностями сервиса, а не поражать умы креативностью наемных дизайнеров. Я думаю, что для создателей действительно оригинальных веб-продуктов, такой подход более чем естественен.
Ссылки
Для более подробного знакомства с PyJamas и связанными с ним технологиями будут полезны несколько ссылок:
| [1] | Сайт PyJamas; |
| [2] | (1, 2) Подборка примеров, Kitchen Sink; |
| [3] | Книга про PyJamas, реализованная на PyJamas; |
| [4] | Google Web Toolkit - предшественник и основа PyJamas; |
| [5] | (1, 2) PyJamas-Desktop - запуск приложений на PyJamas как десктопных; |
| [6] | WebKit |
| [7] | Pyjamas - Python Applications for Desktop and Web на Advogato; |
| [8] | XMLRPC сервер |
| [9] | Web.py - простейшая среда для разработки вебсерверов; |
| [10] | Библиотека JSONRPC для Web.Py; |



