2. Python Enhancement Proposals (PEPs)
● PEP 8 - Style Guide for Python Code
● PEP 20 - The Zen of Python
● PEP 249 - Python Database API Specification
● PEP 257 - Docstring Conventions
● PEP 202 - List Comprehensions
● PEP 3120 - Using UTF-8 as the default source
encoding
● PEP 492 - Coroutines with async and await syntax
3. PEP 8
● 4 пробела на отступ
● Форматирование только пробелами
● Пустые строки между классами и методами
● Запись аргументов функции
● Пробелы внутри выражений
● Документация
● Именование переменных
When applying the guideline would make the code less readable, even for
someone who is used to reading code that follows this PEP.
4. Python StdLib
Чтение csv файла
with open('names.csv') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
print(row['first_name'],
row['last_name'])
Сравнение двух списков
s1 = ['baconn', 'eggsn', 'hamn', 'guidon']
s2 = ['pythonn', 'eggyn', 'hamstern', 'guidon']
sys.stdout.writelines(unified_diff(s1, s2, fromfile='before.py', tofile='after.py'))
Работа с датами
begin = datetime.strptime(‘17/09/17’, "%d/%m/%y")
end = begin + timedelta(days=10)
Работа с архивом
zipfile = ZipFile(zip_file)
zip_names = zipfile.namelist()
for zip_name in zip_names:
If zip_name.endswith(‘.txt’):
zipfile.extract(zip_name)
Работа с БД
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute('SELECT SQLITE_VERSION()')
print(cursor.fetchone())
>>> ('3.19.3',)
Простейший HTTP сервер
$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
5. Продуктивность
Python, в целом, наиболее краток,
даже в сравнении с функциональными языками.
https://arxiv.org/pdf/1409.0252.pdf
https://blog.codinghorror.com/are-all-programming-languages-the-same/
11. asyncio
import asyncio
async def foo():
print('Running in foo')
await asyncio.sleep(0)
print('Explicit context switch to foo again')
async def bar():
print('Explicit context to bar')
await asyncio.sleep(0)
print('Implicit context switch back to bar')
ioloop = asyncio.get_event_loop()
tasks = [ioloop.create_task(foo()),
ioloop.create_task(bar())]
wait_tasks = asyncio.wait(tasks)
ioloop.run_until_complete(wait_tasks)
ioloop.close()
Running in foo
Explicit context to bar
Explicit context switch to foo again
Implicit context switch back to bar
14. Реализации
● Cpython → LLVM
● IronPython → .Net
● Jython → JVM
● Cython → C
● Grumpy → Go
● MicroPython → микроконтроллеры
● PyPy → LLVM, .Net, JVM с JIT-компиляцией
15. Cython
cpdef int myfunction(int x, int y=2):
a = x - y
return a + x * y
cdef double _helper(double a):
return a + 1
cdef class A:
cdef public int a,b
def __init__(self, b=0):
self.a = 3
self.b = b
cpdef foo(self, double x):
print x + _helper(1.0)
> cython --embed example.pyx -o example.c
> gcc -g -O2 -o example example.c `python-config --includes --ldflags`
17. Python 3.6
● Форматирование строк:
name = "Fred"
f"He said his name is {name}."
● “Читаемость имеет значение”:
1_000_000 или 0x_FF_FF_FF
● List comprehensions
result = [i async for i in aiter() if i % 2]
result = [await fun() for fun in funcs if await condition()]
● Словарь потребляет на 20% меньше памяти
● Скорость работы на 10% больше
Всем привет! Меня зовут Тыщенко Виктор, я backend team-lead в компании 3d4medical. Вижу, тут собралось много людей, любящих решать задачи и интересующихся чем-то новым. У каждого из нас есть свои способы, свои проверенные инструменты и, в конце концов, любимые языки программирования. Я же хочу рассказать о своём, который помогает сосредоточиться на задаче, а не заставляет бороться с компилятором и вспоминать какие-то низкоуровневые конструкции.
Питон
Что за зверь? Первая его версия вышла более 20 лет назад, причём написал его человек, получивший образование именно в сфере разработки языков программирования. Это не могло не сказаться на архитектуре - она достаточно логична и расширяема, что не предвещает какой-либо поломки обратной совместимости.
Процесс разработки полностью стандартизован и описан в так называемых PEP. То есть сначала описывается некоторая функциональность, обсуждается, исправляется, и лишь потом реализовывается в языке. Многие скажут, что слишком много бюрократии, зато в итоге получается отличная документация, в которой описано не только что именно сделано, но и почему или для чего. За деталями реализаций смотрите уже исходники. Самые известные PEP8 и PEP20.
В PEP 20 приведены неформальные правила разработки, так называемый Дзен Python. "Явное лучше неявного", "должен быть оди и желательно только один очевидный способ сделать это". На самом деле я бы не сказал, что они применимы только для python, это некая философия программирования. Бывало, кидаешь pull request, а тебе так "увидев двойственность, отбрось желание угадать" - и сразу понятно где именно баг и как надо переделать. Или "читаемость имеет значение", и ты уходишь переписывать так, чтобы глаз не спотыкался на синтаксических конструкциях.
pep8. В нём описан стиль кодирования. Любой питон-разработчик читает чужой код как свой. Больше нет споров ставить ли пробел после запятой или табы vs пробелы. Этот стандарт обязателен для соблюдения при работе в команде, но тем не менее компилятор не будет ругаться в случае его нарушения. На слайде лишь маленькая часть, но я настоятельно советую ознакомиться с ним целиком. Он довольно интересен и местами даже философичен. Например, там есть указание, когда стандарт может не применяться - я не стал переводить цитату.
Что очень важно - python поставляется с батарейками. Его стандартная библиотека очень обширна: тут есть и работа с аудио, и с архивами, комплексными числами, json, http и тому подобное. На примерах со слайда можно убедиться насколько проста работа с этим языком. Отформатировать дату - легко, поднять HTTP сервер - одной командой, выгрузить что-то в csv или sql - да пожалуйста! И что мне ещё нравится - ни одной лишней конструкции, всё очень лаконично.
Собственно, это ещё один плюс языка - чтобы выразить свою мысль не надо растекаться по древу и создавать структуры, выделять память, открывать ридеры от стрима, а потом ещё не забыть всё это дело освободить. Пожалуйста, избавьте меня от этого - мне всего лишь нужно прочитать первую строчку файла, дайте сосредоточиться на задаче.
Так что благодаря высокой ёмкости и лаконичности языка, а также огромному репозиторию пакетов, программы на python занимают минимум строк и пишутся за минимальное время. В некоторых книгах не сразу даже понятно - то ли это код на python, то ли псевдокод.
Python изначально разрабатывался как универсальный язык программирования, так что он поддерживает множество парадигм. Здесь есть и всем привычные классы, и лямбда-функции с map/reduce, и декораторы, и возможность легко создавать свой DSL, которых на самом деле полно. Одних ORM популярных штуки 3. Также я видел модули, написанные целиком в функциональном стиле, или пакеты, одно лишь подключение которых меняет поведение вашей программы. А всё благодаря отличной интроспекции.
Вы можете посмотреть список слотов объекта, изменить их значения, добавить новых. Например, вы можете написать декоратор deprecated, который модифицирует строку документации, добавляя туда предупреждение, что функциональность устарела. Кстати, JetBrains в своём дебаггере пошли ещё дальше - они модифицируют байт-код функции ещё до её выполнения. Но это тема уже отдельного доклада.
Итак, где же он используется? Здесь лишь небольшой список продуктов, которые активно крутятся в продакш. Да, это высоконагруженные проекты, которыми мы пользуемся каждый день. Я специально оставил пустое место для вашего. Большинство из них вырастало из небольших прототипов, сделанных за пару месяцев. И ведь это очень удобно - сделать прототип, а потом точечно наводить оптимизацию.
Я это прочувствовал на собственном примере, когда создавал свою игрушку GeoPuzzle. Само ядро было написано недели за 2 по вечерам после работы, потом лишь упрощал админку и оптимизировал работу: что-то вынес в кеш, что-то в хранимку Postgres, поменял формат данных, подключил React/Redux. В итоге могу загружать прям оригинальные полигоны по 100 Мб с OSM, а информацию для инфобокса тянуть с Википедии. Так что подключение новой страны или района занимает минут 20.
Если же говорить о сферах применения, то
- он нашёл своё место в DevOps в виде популярных Ansible и Salt; если вам кажется странным синтаксис bash, попробуйте перейти на python;
- на нём пишут GUI приложения - есть биндинги к Qt, GTK, Glade для всех популярных платформ
- работа с данными, моделирование, построение графиков (numpy, pandas, matplotlib)
- распознавание образов - OpenCV
- парсинг сайтов - тот же Scrapy позволяет в декларативном стиле описывать что именно и с каких страниц мы должны собирать, а также модифицировать эти данные с помощью pipeline'ов ещё до сохранения на диск
- библиотек для написания ботов просто валом, а уж руководств так вообще несчесть
- ну и конечно же web-фреймворки: от простейших bottle и flask, до монстров типа django и pyramid. Кстати, на горизонте появилась ещё один: aiohttp.
В Python 3.5 наконец-то появилась нормальная аннотация для async/await, что послужило толчком к написанию всяких асинхронных библиотек к сторонним сервисам на базе asyncio и event loop. Уже готовы библиотеки для работы с postgres: aiopg и asyncpg; redis - aioredis; http server - aiohttp, sanic, - что ещё для работы нужно? :) Ниже я привэл пару примеров, чтобы показать, что это совсем не сложно, и код получается понятным.
На самом деле asyncio - очень важная часть современного python, можно сказать, что это аналог горутин. По сути вы запускаете свой менеджер процессов внутри одного из потока интерпретатора (https://stackoverflow.com/questions/29703620/asyncio-event-loop-per-python-process-aioprocessing-multiple-event-loops). Это существенно снижает накладные расходы на переключение между задачами. Справа приведён код для примера, что очень важно - есть возможность писать асинхронный код как синхронный.
Но первоначальная реализация была так скажем медленной. Встречайте uvloop, все мы любим бенчмарки, померяться циферками. На верхнем графике кол-во обработаных запросов за 30 секунд с concurrency 300. Как видите, асинхронность в python вполне может потягаться с реализациями на Go или Node.js. На нижнем графике скорость чтения строк из postgres для разных библиотек. Надо всё-таки заметить, что авторы графиков здесь всё-таки немного лукавят - и httptools, и asyncpg написаны не на стандартной реализации CPython, а на Cython - код которого надо транспайлить в C, а потом компилировать gcc. Хоть это и звучит страшно, но ставится всё той же командой pip install asyncpg. Так что это не мешает использовать их в вашей программе.
И тут часто задают вопрос: Как такое может быть? Питон же очень медленный! Выбросьте этот миф вместе с кодом на python 2.7. Как правило, вы будете упираться в производительность сети, но уж никак не CPU. В этой статье автор подкрепляет свои слова кучей исследований. Но даже если вам уже мало скорости работы виртуальной машины python, то можете реализовать узкое место на каком-нибудь низкоуровневом языке. Кстати, все узкие места давно заоптимизированы и переписаны на C: библиотеки для работы с XML, графикой или БД - их C-часть либо идёт в pip файле, либо ставится через apt-get. Благодаря продуманной системе биндингов, вы можете переписать отдельные места хоть на Rust, оставив логику на более высоком уровне. Так, например, делает EVE Online, которая целиком написана на Python, с оптимизацией узких мест кодом на Cython. Кстати, на тему игр - во многих из них на python пишутся некие высокоуровневые сценарии, которые в свою очередь дёргают методы движка.
Да, на самом деле Python это не только основная реализация CPython, но также и набор соглашений тех самых PEPов, основываясь на которых, было создано несколько интерпретаторов для других платформ. Например, Jython, который работает поверх JVM, или IronPython поверх .Net. Проект Grumpy, который затеял Google для конвертации Python кода в Go. Так что Python может быть как интерпретируемым, так и компилируемым - всё зависит от конкретной реализации.
Код на Cython вообще транслируется в C, который потом компилируется обычным gcc. Да-да, есть возможность писать низкоуровневый код так, чтобы он был понятным. На примере я хотел показать как он выглядит. Всё то же самое - классы, функции, методы. Скорость выполнения не уступает аналогичной на C, но вы можете импортировать его как обычный пакет в свой код на CPython. Даже более того, это считается стандартной практикой - тот же uvloop - обёртка на Cython над системной библиотекой libuv. Та же история и с lxml.
О, да, статическая типизация! Как же мне её не хватало. Когда в переменной вдруг оказывается список - начинаешь недоумевать, и идёшь по стеку в поисках той сволочи, которая вернула результат не в том виде. Ну да, тесты помогают, но много ли их пишется? Кстати, кто пишет тесты? А у кого coverage больше хотя бы 95%? Вот вам ещё один способ проверки, что код работает как вы задумали - в 3.5 появилась возможность указывать типы. Не будет больше ошибок типа undefined is not a function. Так что все сложные и критичные вещи типа биллинга я стараюсь писать с вот такими вот подсказками. Правда, пока эта проверка только на этапе написания кода, но в дальнейшем с её помощью можно существенно оптимизировать расход ресурсов. Вы ж сами рассказываете интерпретатору где какие типы использовать, грех этим не васпользоваться. Так что проставляйте типы, это пригодится.
Кстати, о новых фичах. Каждый новый релиз всё вкуснее и интереснее. В недавнем 3.6 добавили ещё один способ форматирования строк. Думаю, многим придётся по вкусу. Позаботились о числовых константах - теперь разряды можно разбивать символами подчёркивания для наглядности. В каком ещё языке столько внимания уделяют читаемости? API asyncio наконец-то стабилизировался и проник в list comprehensioin, а оптимизация некоторых его классов дала прирост производительности аж в 30%. И, что не может не радовать - оптимизация среды выполнения. Если кому интересно, после доклада могу рассказать как спустя 10 лет разработчики нашли способ оптимизировать рантайм аж на 10%.
На самом деле тема Python весьма обширна. Сложно уложиться в 30 минут. Есть много интересных тем: GIL, создание desktop-приложений или ботов, работа с различными библиотеками и фреймворками. Так что у меня к вам просьба: если тема интересна, отловите меня и поделитесь о чём ещё хотите услышать. Я обязательно передам эту информацию организаторам.
На этом всё, спасибо за внимание!