Одна из отличительных особенностей языка Python — это посвящённые этому языку конференции, так называемые PyConы. Не так давно мне удалось побывать на одном таком PyCon-е — EuroPython 2014. EuroPython — это одна из наиболее крупных европейских ежегодных конференций по языку Python, которая три последних года проводилась во Флоренции, а в 2014м — первый раз в Берлине. Пока свежи воспоминания решил написать небольшой отчётик — что и как было.
Вместо введения
Сразу оговорюсь, тут будут исключительно впечатления и короткие тезисы, и не будет подробного пересказа содержания докладов, так как при большом желании все их можно посмотреть на YouTube — организаторы данной конференции мало того, что не стали делать из видео выступлений какую-то коммерческую тайну, так ещё и организовали прямую трансляцию всех этих видео (кстати, видео с прошлогодних конференций тоже можно отыскать в открытом доступе на том же самом YouTube).
И ещё. Далеко не все доклады затрагивали Python напрямую. То есть зачастую в докладах шел обзор каких-либо полезных технологий, и немного сбоку рассказывалось, как эти технологии можно использовать в мире Python. Поэтому если в процессе прочтения некоторого абзаца данного опуса у вас возникнет мысль «так а где же тут питон? o_O» — советую сразу посмотреть видео — там все будет.
Начну с того, что практический каждый день конференции строился по расписанию: сутра — Keynotes, потом доклады — по 20-45 минут каждый (с перерывом на обед и кофебрейки), под вечер — Lightning Talks. Думаю, тут стоит поподробнее сказать что же такое Keynotes и Lightning Talks.
Keynotes — это такие доклады, не сильно технические, с большим обилием философии. На мой взгляд, практического применения в них мало, поэтому в своем повествовании я их упущу.
По поводу Lightning Talks — это такие продолжительные сессии часа так на 1.5, в течении которых любой желающий мог выйти и высказаться. На каждое выступление давалось порядка 10ти минут. Среди этих вот мини-докладиков было достаточно много флейма (реклама своих продуктов, реклама всяких event-ов, типо PyCon-а в Бразилии, какие-то общие философские мысли и т.п.). Поэтому в своем рассказе я постараюсь отразить только те выступления, которые мне показались наиболее полезными и интересными.
День первый (Python vs Haskell)
Поскольку в первый день было открытие конференции, то докладов и чего-то более-менее полезного было мало. Собственно, самый главный доклад дня: чему Python может поучиться у Haskell-а. На самом деле, в докладе речь шла не только про один Haskell, но и немного про Erlang, но это не суть важно. Основная мысль доклада сводилась к тому, что статические анализаторы кода ни разу не отлавливают ошибки вида 1 + "1", и что всему виной динамическая строгая неявная типизация в Python, что влечет за собой проблемы рефакторинга и т.п. Варианты решения — использовать аннотации (привет, Python 3), использовать экспериментальный вариант интерпретатора Python: mypy, который на уровне синтаксиса языка позволяет задавать типы у аргументов функций. То есть можно писать вот так:
def fib(n: int) -> None:
a, b = 0, 1
while a < n:
print(a)
a, b = b, a+b
и это будет корректно восприниматься интерпретатором. Конечно, штука довольно интересная, вот только опять-таки это работает только для кода Python 3. Я попробовал поискать mypy в стандартных репах Debian и не нашел, а компилять вручную как-то лениво. Возможно от него был бы толк, будь он чуть более распространен, была бы поддержка на уровне IDE и т.п. (кстати докладчик активно призывал контрибьютить в этот проект). Так же прозвучали утверждения, что mutability есть зло, а так же про слабую поддержку Python-ом алгебраических типов данных. Все это на мой взгляд очень и очень спорно. Тем не менее я рекомендую посмотреть видео доклада хотя бы, чтобы иметь представление о том, что творится в других языках (ну и конечно же чтобы быть готовым к аргументированному спору в холиварах аля “какой язык лучше”).
Так же мне запомнился один доклад из Lightning Talks, парень (кстати из России), пиарил свою библиотечку под названием Architect, главное преимущество которой — добавление возможности автоматического партицирования таблиц в БД посредством ORM (поддерживаются модели Django, SQLAlchemy, Pony). Из баз данных — MySQL и postgreSQL. Людям, кто работает с этими базами, возможно данная либа иногда может быть полезной.
День второй (nix, Kafka, Storm, Marconi, Logstash)
Прозвучал довольно интересный доклад про пакетный менеджер nix. На сам деле есть целый дистрибутив, построенный на этом пакетном менеджере. И называется он NixOS. Его полезность, если честно, мне кажется несколько сомнительной, а вот сам пакетный менеджер nix в некоторых кейсах может быть весьма полезен (особенно учитывая тот факт, что он не запрещает использование основного пакетного менеджера, т.е. yum или apt). Основная фишка данного пакетного менеджера заключается в том, что все операции, производимые им, не являются деструктивными. То есть грубо говоря при установке каждого нового пакета, предыдущая версия пакета не затирается, а создается новое пользовательское окружение, с новым набором симлинок. Это позволяет:
- 1. в любой момент времени откатиться до некоего предыдущего состояния пользовательского окружения
- 2. одновременно использовать несколько версий пакетов (т.е. например несколько версий ffmpeg-а, или несколько версий python-а). И это все без всяких обвесок в виде виртуализаций, докеров и т.п.
- 3. при апдейтах нет вероятности поломать систему, т.к. старый пакет при обновлении не сносится, а новый пакет ставится в некоторое обособленное окружение, а в конце установки происходит переключение симлинок
Из минусов — если хранить все версии пакетов со всеми зависимостями, то естественно места на HDD потребуется больше и в довесок мы получаем некоторую избыточность пакетов. На мой взгляд, это недостатки с которыми можно мириться. Так же в докладе кратко рассказывалось, как можно собирать свои пакеты для nix, и в частности, python-ячьи пакеты. В общем, если есть проблема Dependency hell, то nix позволяет решить эту проблему довольно элегантно.
В этот же день был доклад про потоковую обработку больших объемов данных с использованием Kafka и Storm. Единственное полезное, что я вынес из этого доклада, это то, что Storm отлично подходит для обработки непрерывных потоковых данных (а не статических, в отличии от Hadoop), а Kafka даст гигантскую фору rabbitMQ в плане дичайшей пропускной способности сообщений (100k+/sec сообщений на ноду против 20k/sec у rabbitMQ), но при этом проигрывает в плане топологии распределения сообщений между consumer-ами. В контексте доклада две данные технологи рассматривались вместе, и Kafka выступала в качестве транспорта для доставки сообщений в Storm.
Был неплохой вводный доклад про Marconi — это система messaging-а в рамках OpenStack (кто не в курсе, OpenStack полностью написан на python). Marconi используется в качестве связующего звена между компонентами облака OpenStack, а так же к качестве обособленного сервиса уведомлений. Собственно является прямым аналогом SNS и SQS от Amazon-а. Предоставляет RESTfull API, может использовать MongoDB, Redis а так же SQLAlchemy в качестве хранилища сообщений (правда SQLAlchemy не рекомендовали в production из соображений производительности), поддержки AMPQ протокола нет, но планируют добавить в будущем.
Ещё был доклад про Logstash / Elasticsearch / Kibana — набор мегаполезных утилит для сбора, фильтрации, хранения, агрегации и отображения логов. Кстати говоря, полезность logstash несколько раз упоминалась в различных докладах от разных людей. Лично я ничего особенно нового именно из этого доклада не услышал. Одна из идей, которая рассказывалась на данном докладе — как при помощи logstash отслеживать все логи из одного request-а, а так же собирать воедино все связные по единому признаку логи от всех компонент распределённой системы. Кстати, в ходе доклада была упомянута интересная библиотечка для логирования под названием Logbook. Судя по описанию, достойная альтернатива стандартной библиотеке логирования в Python.
День третий (Sphinx, gevent, DevOps risk mitigation)
Третий день начался с написания мультиязыковой Sphinx-документации. Данный доклад был весьма полезен для меня лично, потому что в рамках проекта, которым я сейчас занимаюсь, возникала задача поддержки двух языковых версий API документации — английской и русской, при этом хотелось бы сделать этот процесс как можно более простым и прозрачным. На самом деле все довольно просто. Есть такая замечательная GNU утилита gettext, которая активно используется для интернационализации различных OpenSource проектов (думаю, что про gettext все и так знают без пояснений), и есть замечательный пакет sphinx-intl. Из sphinx-овой rst-овой документации при помощи нехитрых команд готовятся *.po файлы, которые потом переводятся в специальном gettext-редакторе, и на основе которых делается документация sphinx под какой-то конкретный выбранный язык. Так же в докладе был упомянут SAAS сервис Transifex, который облегчает труд переводчиков. Насколько я понял, общий принцип работы сервиса такой — при помощи нехитрых консольных утилиток, можно загружать и скачивать файлы переводов на этот сервис, который предоставляет для переводчиков удобный Web-интерфейс для перевода текстов. Консольные утилитки для этого сервиса, насколько я понял, работают по принципу git push/pull. Сервис не бесплатный. Думаю всем заинтересовавшимся (кто сталкивался с проблемой интернационализации) смотреть видео доклада необязательно, достаточно полистать слайды, чтобы все понять.
Из интересных докладов, которые были в этот день: доклад про gevent (я посчитал важным сходить на этот доклад, потому что на gevent-е чуть более чем полностью построен WebDAV-сервис проекта, которым я занимаюсь). На самом деле ничего принципиально нового не рассказали, начали с вводной по реализации асинхронности на Python и закончили собственно gevent-ом. Если кто не знает, что такое gevent — тому данный доклад возможно покажется интересным, ну а тем, кто уже знаком с данной технологией — врят ли. Из услышанных интересностей: 1. web-микрофреймворк, целиком сделанный на gevent-е, с поддержкой PostgreSQL, 2. AMQP-библиотечка, также целиком сделанная на gevent-е.
Ещё был весьма занятный доклад «DevOps Risk Mitigation: Test Driven Infrastructure», про тестировании инфраструктуры в рамках процесса deploy-я. На самом деле никакой магии нет — собирается RPM-ка, раскатывается куда-то на тестовые машины, и далее автоматизированно через rsh заходим на эти машины и тестируем все что только можно, начиная от HTTP proxy и заканчивая системой сбора логов. Докладчик, весьма колоритный old school-ный админ, как я понял, не признает всяких этих puppet-ов / chef-ов / salt-ов, но зато осознает идею того, что для поддержания качества продукта, тестами должен покрываться не только лишь один код. На мой взгляд, идея верная, и это и правда то, к чему надо стремиться. Возможно не такими способами, как говорится в докладе, но тем не менее. Всем DevOps-ам — must see.
День четвёртый (защита исходников, SOA от Disqus, архитектура абстрактного debugger-а, dh-virtualenv)
День начался с замечательнейшего по полезности доклада «Multiplatform binary packaging and distribution of your client apps». Думаю многие программисты, кто пишет коммерческие приложения, хотя бы раз в жизни задумывались над проблемой: «они могут скопировать и прочитать наш код!». То есть иными словами возникает задача — поставлять продукт в зашифрованном виде, ну или же в виде бинарников, из которых выцепить и модифицировать исходный код достаточно проблематично. К слову, Dropbox, у которого PC клиент написан на Python, решает данную проблему довольно геморройно — они кладут в инсталлятор свою собственную патченную версию интерпретатора Python, которая умеет читать зашифрованные *.pyc файлы. Решение, предлагаемое в докладе:
- 1. cythonize-им исходники — переводим их в *.c
- 2. компиляем полученное в native extensions
- 3. собираем exe-шник при помощи PyInstaller-ра
- 4. Упаковываем в setup.exe/dmg/rpm/deb файл
Для больших деталей рекомендую посмотреть видео доклада и слайды. Естественно каждый из 4х описанных мною этапов в докладе разобран более подробно — приводятся образцы кода, как и что делать. Ну и конечно же стоит оговориться, что данного рода обфускация не спасает о реверсинженеринга, когда человек может заимпортить обфусцированный пакет и просто банально пробежаться по именам методов/переменных. Кстати, ещё по данной к теме рекомендую к прочтению вот эту статью (она упоминается в докладе).
Следующим был весьма неплохой доклад от одного из разработчиков Disqus. В докладе говорилось про преимущества SOA-архитектуры на примере сервиса Disqus. Cервис Disqus чуть более чем полностью построен на Django, точнее он разделен на кучу-кучу мелких микросервисов (REST API, worker-ы, cron-ы и т.п.), каждый из которых построен на Django. К слову, докладчик доступно объяснил почему именно Django, а не что-то другое — большое комьюнити, куча готовых решений + намного проще найти специалистов. Если смотреть на технологический стек, то у Disqus из основных компонент используется uwsgi, django, celery, postgreSQL в качестве базы и redis для кэша. Чтобы шарить общий код между своими микросервисами, я так понял, они собирают отдельные python-овские пакетики. Из плюсов SOA подхода:
- 1. независимая масштабируемость
- 2. простота deploy-я
- 3. простота работы с кодом
из минусов:
- 1. если меняется какой-то один API (например external API service), то приходится не забывать догонять под измененный API другие сервисы
- 2. как упоминалось чуть выше — тяжелее шарить общий код между сервисами
Python Debugger Uncovered — вот это очень классный доклад от разработчика PyCharm. Советую всем backend-разработчикам посмотреть для общей эрудиции, как устроен некий абстрактный дебаггер в вакууме. Никакой высокой магии нет, все дебаггеры сделаны по одному принципу и подобию при помощи нативных средств самого языка Python. Кстати, для справки, дебаггеры PyCharm и PyDev объединяются.
Ещё в этот день был очень стоящий доклад про tool-у dh-virtualenv от Spotify. Spotify в качестве основой production ОС используют Debian, и цель создания данной утилиты заключалась в том, чтобы объединить deploy проекта в виде deb-ок с инкапсулированным virtualenv-ом. Общий смысла какой — с одной стороны Debian адски стабилен, а Debian-пакеты удобны тем, что позволяют прописать все не-python-ячи зависимости (типо libxml), с другой стороны virtualenv удобен тем, что позволяет изолировать внутри себя python-ньи зависимости, и все эти зависимости будут самыми свежими пакетами, т.к. взяты с PyPI. Тулза dh-virtualenv позволяет объединить одно с другим, и грубо говоря, автоматизированно собирать deb-ки из текущего развернутого virtualenv-а. Ставится она кстати через обычный apt-get. Внутри проекта, помимо setup.py и requirements.txt создается директория debian, в которой описываются характеристики и зависимости deb-пакета (rules, control и т.п.), а для создания пакета нагоняется консольная команда dpkg-buildpackage -us -uc. virtualenv на конечной qa/prod машине ставить не надо, т.к. он автоматически скачивается и упаковывается утилитой при создании пакета.
Lightning Talks этого дня лично мне запомнился одним очень интересным докладом про то, почему не стоит злоупотреблять getattr().
Пример кода:
import random
class A(object):
def get_prop(self):
return getattr(self, 'prop', None)
class B(A):
@property
def prop(self):
return random.chioce(['test prop1', 'test prop2', 'test prop3'])
print(B().get_prop())
Данный код будет выводить всегда None, т.к. исключение (из-за неправильного имени метода, т.е. random.chioce) будет игнорироваться внутри getattr.
День пятый (особенности работы с памятью, DB API, делаем Go из Python)
Доклад “Everything You Always Wanted to Know About Memory in Python But Were Afraid to Ask” лично мне, как человеку, сильно далекому от C/C++, и привыкшему мыслить более приземленными материями, было очень интересно послушать. Какие-то вещи я уже знал, какие-то вещи лишний раз освежил в памяти. Не буду останавливаться на деталях, скажу так — особенно интересно было послушать про существующие тулы, которые имеют реальное практическое применение (objgraph, профилировщик памяти guppy и т.п.), и про то, что в Python можно заюзать раличные либы, реализующие низкоуровневый malloc(), и какой профит будет от этих замен. В общем, лично я рекомендую всем посмотреть этот доклад. Так же в этот же день проходил ещё один крутой доклад на схожую тему — «Fun with cPython memory allocator». К сожалению, я на него не ходил, но судя по отзывам моих коллег — доклад весьма стоящий. Многие наверное сталкивались с проблемой, когда создаешь в Python список из большого количества строк строк, потом удаляешь его, а память не уменьшается. Вот про эту проблему рассказывается в докладе — как это, из-за чего и как с этим бороться.
Далее был весьма неоднозначный доклад «Advanced Database Programming with Python». Тем, кто в своей практике мало работал с базами данных — рекомендую послушать. Узнаете такие вещи, как уровни изоляции транзакций, например, и чем они отличаются друг от друга, а так же про python-ячью специфику работы с базами данных (согласно PEP 249 autocommit=0 де факто и commit-ы надо не забывать писать вручную) и про какие-то базовые вещи по оптимизации запросов. Доклад неоднозначный, потому что автор делает акцент на множестве весьма редких оптимизаций типо, как например генерить ID вставляемой записи в Python-е, а не полагаться на auto_increment/sequences БД. Это-то конечно хорошо, вот только опыт показывает, что наслушавшись таких докладов, некоторые программисты начинают преждевременно оптимизировать все и вся, и это в 99% случаев приводит к весьма плачевным последствиям.
И последним было выступление от Бенуа Шесно, создателя web сервера gunicorn. Рассматривалось 100500 существующих вариантов реализации мультизадачности в python, и новый 100501-ый вариант — библиотечка offset, привносящая в python функционал кроутин языка Go. Во время выступления я немного покопался во внутренностях данной библиотеки — судя по всему в основе данной либы лежит боле низкоуровневая реализация кроутин основанная на библиотеке fibers. Сама же offset привносит в язык более высокоуровневые обертки. Т.е. грубо говоря, позволяет писать программы на python сродни тому, как они бы выглядели бы в Go. В своем докладе автор как раз приводит примеры схожести кода реализации некой абстрактной задачи, написанного на Go и написанного на Python, но с использованием offset. В общем, всем тем, кому недостаточно существующего функционала тредов, tornado/twisted, asyncio, gevent и модуля multiprocessing — данная библиотека может показаться весьма интересной. Слушать же сам доклад особого смысла не имеет — лучше сразу лезть в код на github и пробовать.
Заключительные Lightning Talks в этот день мне запомнились докладом про HSTS. Очень полезная штука надо сказать, о которой мало кто знает. Фактически это HTTP response заголовок, который указывает браузеру всегда принудительно использовать HTTPS-соединение для данного хостнейма. Т.е. в дальнейшем если пользователь вбивает в браузере some-url.com, то браузер сам автоматически подставит https. Полезно и из соображений безопасности и и из соображений сокращения числа редиректов с HTTP на HTTPS, возвращаемых с сервера.
Беседы в кулуарах
На конференции было огроменное количество стендов от компаний, так или иначе связанных с Python (Google, Amazon, DjangoCMS, JetBrains, Atlassian и пр). К ним ко всем можно было подходить и общаться на разного рода интересующие вопросы. Мы довольно много общались с ребятами из Google (правда это было не на самой конференции, а на after party от Google). Из интересного — Python у них используется преимущественно во внутренних продуктах, ну разве что кроме Youtube-а. Так же они нам по секрету сказали, что разработчики Google не очень-то любят BigTable, и уже сейчас в лабораториях Google готовится к выпуску новая революционная БД (кодовое название Spanner), позволяющая делать распределенные транзакции на кластере, и при этом обладающая всеми плюсами NoSQL. По слухам, вроде как даже Open Source (в чем, конечно, есть большие-большие сомнения).
Так же общались с представителями DjangoCMS (тут ничего интересного, банальная незатейливая CMS на Django, можно установить на свой сервер, а можно использовать SaaS решение) и c представителями Amazon. Касательно последних, задал им вопрос, затронутый на конференции highload 2012го года, по поводу того, что пропускная способность инстансов довольно разная и непропорциональна типу инстанса (см. презентацию — 25ый слайд), но получил в ответ «ну это специфика виртуализации такая, мы не можем сказать почему, обратитесь в поддержку». Кстати, думаю многим будет интересно, ребята из Amazon раздавали анкеты с вопросами на Python-тематику. Уже сейчас не вспомню, то ли они призы разыгрывали, то ли хантили таким образом. В общем, вопросики весьма специфичные, из разряда «эти самые вопросы, которые никогда не встречаются на практике, но их любят задавать на собеседованиях в больших конторах»:
1. Which is called first when creating an object:
a. __create__
b. __new__
c. __init__
d. __del__
2. What is printed by the last statement in:
def foo(x, l=[]):
l+=2*x
print l
foo('a')
foo('bc')
a. ['a','b','c']
b. ['a','bc']
c. ['a','a','b','c','b','c']
d. ['a','a','bc','bc']
3. What does the last statement print?
class A(str):
pass
a=A('a')
d={'a':42}
d[a]=42
print type(d.keys()[0])
a. str
b. A
c. dict
d. int
4. Which of the following will these 2 statements return on Python vesrion 2?
5 * 10 is 50
100 * 100 is 10000
a. True, True
b. True, False
c. False, True
d. False, False
В целом, впечатления от конференции весьма положительные. Основная ставка организаторов делалась на общения в кулуарах. На самом деле, это первая конференция на моей памяти, где доклады прямо сразу же выкладываются на YouTube. И хотя уровень большинства докладов я бы оценил как средний, тем не менее прозвучало довольно много интересных вещей, которые так или иначе можно применить в реальных проектах.
Автор: StraNNikk