Мифы и легенды современного Python

Kate

Administrator
Команда форума
Мы в Evrone часто сталкиваемся с легендой, что для задачи, которая встает перед программистами, есть какой-то волшебный, лучший инструмент. К примеру, если вы хотите сделать что-нибудь бэкендовое, вам обязательно нужен PHP. А если вы хотите создать крутой современный фронтенд, то без JavaScript вам делать нечего. Если же вы такой хипстер, что хотите быстро делать фулстек фичи, то вам просто необходим Ruby. И, наконец, если у вас ML, artificial intelligence, big data или просто вам на бэкенде нужен какой-то клей, чтобы работать с данными, то вам жизненно необходим Python.

Python самый популярный язык программирования в мире​

Начнем с того, что произошло 40 лет назад, когда Гвидо ван Россум только закончил учиться на профессионального автора языков программирования (!), и на фултайм работе делал язык программирования ABC. В 1986 году Гвидо завершил работу над ним, и вместе с тем самым Таненбаумом, который написал толстую книжку, начал делать операционную систему Amoeba. Гвидо надо было делать для неё скрипты, и он как профессиональный разработчик языков программирования, начал делать новый язык для себя. Чтобы создавать скрипты как клей для доступа к к системным библиотекам, написанным на С.

У команды, которая работала над Амебой, была добрая традиция называть программы для этой операционной системы в честь телешоу. Так что язык Python не просто так называется в честь телешоу «Монти Пайтон».

В 2000 году Гвидо присоединился к команде Zope, которая делала пайтоновские фреймворк, инфраструктуру и т.д.. Это можно считать стартом мировой популярности Python.

Python лучший язык для обучения​

Ноги Python растут из из языка ABC, который пытались сделать для обучения новичков. Но это было 40 лет назад, с первого раза у Гвидо не получилось, зато неплохо получилось со второго.

Когда Python был создан, его разработчики написали Zen of Python — манифест из 10 пунктов, который подчеркивал основные ценности языка. Например, что «simple is better than complex, but complex is better than complicated», разумные принципы программирования. Python считается очень хорошим языком для обучения, лучшим, чем JavaScript, потому что он придерживается принципа «минимального удивления». Новые разработчики минимально удивляются поведению кода, который они написали. Python логичен, предсказуем и большинство штук в нем нужно делать, руководствуясь еще одним принципом из Zen of Python: «явное лучше неявного».

К сожалению, у такого подхода есть обратная сторона. Software complexity problem, с которой боремся мы, программисты. Python как язык похож на кочан капусты, и его простота, это лишь внешний слой. Но чем глубже разработчик погружается, тем больше всякого разного предлагает язык программирования. В глубине его сокрыт инструментарий, чтобы делать действительно большие проекты. Там есть метапрограммирование, декораторы, куча специализированного синтаксиса, огромная стандартная библиотека. Python, который используется в больших проектах на миллионы строк кода, это не тот Python, которому обучают на курсах «войти в IT». Язык прост в начале, но чем больше мы используем этот инструмент, тем больше разных фишечек он нам предоставляет, чтобы мы могли создавать сложный софт.

Python очень хорошо документирован​

Когда я в 90-х начинал писать код, для меня золотым стандартом документации был MSDN, который действительно объяснял, как правильно программировать под Windows. Другой пример хорошей документации — это Qt, там было множество примеров, после несколько сотен страниц становилось понятно, что вообще делать. Сейчас документация Python вобрала в себя все лучшее за последние 30 лет.

Python документирован очень хорошо. Не только сам язык, его синтаксис, семантика, но и стандартная библиотека. На официальном сайте огромное количество примеров в разделе документации. Новый разработчик прочтет там не только «что», но и «как». А опытный разработчик найдет нюансы использования с примерами, сможет сразу посмотреть, как правильно.

Python имеет в комплекте «батарейки»​

В стандартной библиотеке Python более 200 модулей для того, чтобы работать с данными, работать с форматами файлов, отсылать и принимать почту. Огромное количество штук Python может сделать «из коробки».

У «батареек» есть обратная сторона. Стандартная библиотека очень быстро устаревает и, к примеру, та ее часть, которая связана с сетевыми запросами, уже много лет назад была заменена мега популярной библиотекой Requests.

Недавно в комьюнити Python была неприятная ситуация, когда один из очень известных контрибьюторов сделал библиотеку для того, чтобы декораторами просто и читаемо описывать структуры данных. Дальше он поговорил с Гвидо, в стандартной библиотеке сделали простенькую альтернативу dataclasses. После чего автор изначальной библиотеки начал получать сообщения типа: «Нафига ты этот велосипед изобретаешь, если в стандартной библиотеке все есть?». Но в стандартной библиотеке это очень простенькая штучка, а он делает полнофункциональную.

Есть когнитивное искажение, что если что-то есть в стандартной библиотеке, то не надо изобретать велосипед. Поэтому наличие этой огромной стандартной библиотеки в какой-то мере тормозит развитие Python. Она маскирует наличие альтернатив. Условно, когда мы в гугле ищем, как распаковать zip-архив в Go, то мы сразу видим библиотеки, которые делают это правильно. С Python мы сразу видим стандартную библиотеку. Даже если эта часть устарела на 10-20-30 лет, альтернативы еще надо поискать.

Python очень популярен в науке​

Есть мнение, которое я часто встречал в аналитике и у знакомых питонистов. Возможно, Python популярен в науке не потому, что он делает для науки что-то особо крутое. Возможно, он популярен, потому что ученые — это не программисты.

Гвидо сделал Python как клей для доступа ко всяким системным штукам. Python с самого начала хорошо мог в C, C++, Fortran — а это как раз то, что в те времена использовали ученые для работы с данными и экспериментами. Ученым нравилась простота изучения Python, им дальше простого первого слоя языка копать не было необходимости. А когда ученые начали использовать язык, он проник в образование и получилось самоподдерживающееся пророчество: учёные используют Python, обучают своих студентов, те из них, кто остается в образовании, тоже используют Python в обучении. Так за 30 лет Python очень надежно проник в науку.

Синтаксис многих популярных решений для Python, например, numpy, близок математикам. Сейчас считается, что Python это инструмент по умолчанию для ML и Data Science, что это привычный инструмент для математиков, ведь за десятилетия этого самоподдерживающегося пророчества выросла огромная экосистема для работы с данными и ML: TensorFlow, AirFlow, Pandas и множество других систем.

Python медленный​

Python интерпретируемый язык программирования. Но сейчас интерпретируемость это совсем не то, что было 30 лет назад. Тогда говорили, что Basic интерпретируемый, и подразумевали, что есть некая программа «basic», которая берет текст программы на языке программирования Basic, построчно читает, разбирает и выполняет.

С современными языками программирования это, конечно, не так. Все современные языки программирования компилируемые. Просто некоторые, например, Java, сперва компилируется в байт-код, а потом виртуальная машина Java этот байт-код компилирует в машинный код. Или, как в случае С или Rust, у них нет виртуальной машины, семантика чуть беднее, поэтому они сразу компилируются из текста в машинный код.

Python компилируется из текста в байт-код и далее виртуальная машина Python, программа python.exe, этот байткод выполняет. Байт-код — это маленькие инструкции, каждая из которых делает какую-то часть работы программы. Для Python они довольно хорошо оптимизированы, как и его виртуальная машина. Она не компилирует машинный код, потому что пока есть виртуальная машина, язык может обеспечить гораздо более богатую семантику, чем то что нам предлагает, к примеру, JavaScript.

Виртуальная машина сама по себе медленная, это не машинные коды, это все-таки программа, которая выполняет байт-коды. А еще есть Global Interpreter Lock (GIL). Виртуальная машина Python предпочитает одновременно выполнять байткод python только в одном потоке. Это придумано для того, чтобы можно было сделать очень быстрый сборщик мусора и защитить структуры данных в памяти от конкурентного использования.

Это не значит, что Python не может выполнять код параллельно. Он не может свой байт-код выполнять параллельно, а чужой нативный код может. Как только байткод начал делать что-нибудь системное, например, читать из файла, или писать в сетку, он поднимает GIL, и какой-то другой поток может начать выполнять высокоуровневую логику байткода. Плюс, стандартная библиотека позволяет хорошо раскладывать Python на процессы. Но все это не мешает ему быть в худшем случае раз в сто-двести медленнее, чем С.

Python популярен в вебе​

Python не самое популярное решение для веба, однако многие питонисты делают фулстек веб-приложения, и еще большее количество программистов делают на Python свои API.

3b0caca96d6218cc987e15504d7432b9.jpg

Почему так, почему не PHP? Потому что в конце нулевых Python как раз начал замещать PHP и Perl, вышел фреймворк Django, который вдохновился очень популярным тогда фреймворком Ruby on Rails. Считается, что Django взял лучшие моменты из Rails и добавил традиционно хорошую документацию. А Гвидо с 2005 года начал работать в Google над App Engine. И это считается одной из ключевых вех в популярности Python, потому что язык стал пиарить Google, как язык «по умолчанию» чтобы делать веб-приложения для Google App Engine. Python занял нишу между PHP и Java, когда PHP уже слишком мало, а Java это слишком много.

За Django последовали другие фреймворки, но в начале десятых случился современный фронтенд, к нам пришли React, Angular, Vue и сожрали фронтендовую часть фулстека. Но в 2019 году Python немного отыгрался FastAPI, о котором поговорим чуть ниже.

У Python беда с управлением зависимостями​

Десятки лет назад библиотеки для Python жили на сайте Vaults of Parnassus. Каждая библиотека была архивом с текстовичком о том, как ее добавлять свою программу. В 1998 году разработчики в версии 1.6 языка добавили в стандартную библиотеку модуль distutils, который ввёл понятие distribution package — zip-архив, который можно скачивать и устанавливать в виде install package.

С установкой приняли спорное решение, которое во многом прокляло зависимости Python. Авторы посмотрели на огромный архив Vaults of Parnassus и решили, что заставлять каждого разработчика приводить библиотеки к общему виду никто не будет. Придумали, что в install package будет файл setup.py, и его просто будут запускать. А в файл setup.py разаработчики зависимостей сами напишут какой-то код, который будет ставить зависимость, как написано в текстовичке. Копировать нужные файлы в какие-то директории, вносить необходимые изменения. А дальше то, что поставилось, уже можно использовать в своем коде. Главная проблема была в том, что setup.py мог выполнять любой Python-код, и поэтому когда сейчас мы делаем pip install, начинают выполняться все setup.py файлы, и мы не представляем себе, какие зависимости поставятся, что поменяется, и что вообще произойдет.

Сообщество Python пытается это побороть сложности, но язык редко определяет работу с зависимостями. Например, npm это не часть JavaScript, Maven это не часть стандарта Java, gem до недавнего времени не был частью Ruby, composer не часть PHP.

Так выглядит экосистема работы с зависимостями Python в 2022 году:

b341ef2b32c1a80c7bbac0223fc3aa72.jpg

Это популярные тулзы, которые сейчас используются, чтобы управлять зависимостями в Python. И, на секундочку, у Python есть логотип сложности управления зависимостями — Утконос. Представляете, у языка есть логотип того, насколько сложно управлять зависимостями!

ae8a8ae75b6bd488fa363911f2ee9e1f.jpg

Python взял лучшее из статического и динамического типизирования​

Традиционно типы считают крутым инструментом, чтобы сократить число ошибок в программах. И Википедия согласна, что типы — это чтобы было меньше багов. Динамическое и статическое типизирование, это про то, кто расставляет типы, «капканы для ошибок». В случае динамического типизирования типы расставляет язык программирования, в случае статического — программист.

У динамического типизирования традиционным плюсом было то, что так как язык за нас расставляет типы, мы можем со страшной скоростью писать код. Минусом было то, что капканы срабатывают, как правило, не сразу, а на этапе выполнения. Иногда капканы могут вообще не поставиться.

В статически типизированном языке код пишется медленнее, потому что нужно руками расставлять капканы. Rust в этом плане особенно показателен. Например, я расставил три капкана, которые мне интересны, и говорю ему, ну ты там остальные сам выведи, а Rust такой: «Я не понимаю, что там, давай, ты мне уточнишь». Я смотрю, и тоже не понимаю, что там. Ну и дальше идет получасовая сессия в попытке натянуть код на глобус. Зато при статическом типизировании капканы срабатывают сразу.

Python ввёл Gradual Typing — лучшее из обоих миров, когда мы в начале фигачим без типов (их расставляет язык), а потом, когда код стабилизируется, добавляем типы только там, где надо. Это позволяет иметь в программах существенно меньше багов и высокую скорость разработки одновременно.

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

74d3a9734a657f93384f4c4a135c7612.jpg

То, что после двоеточия, это типы, и они используются в качестве DSL, чтобы описать данные. Мегапопулярный FastAPI теперь точно так же использует типы, чтобы описывать API. Как в Ruby DSL использовался 20 лет назад, чтобы писать лаконичный, идиоматичный код, так сейчас программисты на Python научились использовать типы, чтобы писать такой же лаконичный и идиоматичный код.

Какой Python сейчас,…​

Python поддерживается крупнейшими мировыми IT-компаниями. Он уже развивается не одним человеком, много лет избираемый steering council из нескольких core-разработчиков работает над языком.

У Python стабильный цикл релизов поддержки, end of life, security фиксов. В Python регулярно появляются новые фичи, в 3.10 появился, например, pattern matching, что очень круто.

Разработчики Python стараются демонтировать устаревшую стандартную библиотеку, изучают возможности отказа от GIL, сейчас есть даже работающая версия, которая убирает GIL и при этом работает быстрее.

Внедряется асинхронность, Django и Flask не так давно перешли на асинхронные рельсы, и активно делаются решения, которые на одном ноутбуке позволяют легко держать 10 тысяч асинхронных подключений в секунду.

И, конечно же, идет битва с зависимостями. Есть pipenv, которое пытается как npm в NodeJS, чтобы npm install, или как gem в Ruby, gem install, чтобы одной командой все работало.

… и каким он станет в будущем​

Есть две ключевые идеи, которыми я бы хотел завершить свой рассказ. Во-первых, сайт Real Python, который содержит исчерпывающую, крутейшую документацию о Python. Это сотни обучающих статей, каждую из которых писали несколько разработчиков и редактировали несколько редакторов. Наверно, лучшее по обучению, что сейчас есть в мире, и при том бесплатно. Они зарабатывают деньги на видеоуроках, но тексты бесплатны.

Во-вторых, Python из-за его легкости в изучении, распространении в образовании и сильной позиции в современной разработке, стал де-факто языком для того чтобы «войти в IT». И многие HR говорят, что это очень сильно размывает пул разработчиков. Из сотни откликов на вакансию питониста людей с опытом больше пяти лет не так много, а большинство окончили трехмесячные курсы и хотят войти в IT. Есть опасение, что вот эта мегапопулярность может серьезно пошатнуть позиции Python. Или нет?


 
Сверху