[recovery mode] Python: рефлексия
© https://www.behance.net/Dinafrik
Я пишу на Python примерно с 15-го года. Я определённо люблю его. Он так прост… В этом эссе я хотел бы вспонить, как начались мои взаимоотношения с этим замечательным языком, что за всё это время я узнал, что заставляло меня пищать от восторга, и рвать на голове волосы от разочарования. Я хотел бы проследить эволюцию языка и себя самого как польлзователя этого языка на протяжении этого не такого уж и долгого промежутка времени. И наконец, я хотел бы попытаться найти ответ на вопрос — почему же я от него отказался?
Перед тем, как перейти на Python, я какое-то время писал на Ruby, баловался Perl’ом, и только слышал, что есть, де, какой-то там «питон». Опробовать же его в деле я по какой-то не понятной причине долго не мог собраться. Что меня останавливало? Сейчас уже и сам не знаю точно… Помню, прочитал статью на википедии о нём, и удивился — язык-то аж 89-го года! Ну что интересного может быть в таком «динозавре»? Отталкивало и название — «питон». Ну что за …? От Ruby я тогда был в восторге, но подспудно ощущал — что-то не то… Не буду сейчас о Ruby — статья не об этом, может в другой раз расскажу. Однако, в один прекрасный день мы решили делать новый проект именно на Python, и всё заверте…
Это была любовь, эмм, с первой строчки (?). Какой же он всё-таки простой. Не отвлекаясь на синтаксис, можно сразу сосредоточиться на решаемой проблеме. Основные концепции языка — тоже предельно просты. Всё происходит явно, даже передача объекта в собственный метод — пресловутый self
. Стандартная библиотека и «магазин сыра» — казалось, Python приспособлен к любой задаче. Задачи, правда, в те времена были попроще. В общем, писать на нём было одно удовольствие. И я писал. Писал, и удивлялся — как я протянул со знакомством до сих пор?
Особенно хорошо он смотрелся на контрасте с тем же Ruby: если вам что-нибудь говорят такие ключевые слова, как rvm
, rbenv
, то вы меня поймёте. Запуск интерпретатора — это просто $ python script.py
. Второй Python, правда, был всё ещё в ходу, это несколько сбивало с толку. Никаких странных символов вроде доллара, никаких точек с запятой — как выражался тогда мой коллега — «just plain English» (он так и про Ruby говорил, правда). Zen of Python, опять же.
There should be one-- and preferably only one --obvious way to do it.
import this
В общем, я был очарован. Я писал очень много кода на Python. Писал, и писал…
Со временем стала расти сложность проблем, которые мне приходилось решать. Потребовалось распарралелить вычисления — не проблема, вот тебе пожалуйста multiprocessing.map
. Стало этого мало — дерижируй потоками (или процессами) напрямую. Вот я впервые написал многопоточную программу. Как и всё прочее, это было просто — не считая врождённых проблем многопоточного программирования, таких как синхронизация доступа. Что там за проблема с GIL, я тогда представлял смутно.
Вот я написал «демона» — программу, предназначенную работать всегда. И снова — обработка сигналов очень проста.
Повышалась сложность, росла и моя экспертиза и в языке, и в программировании. Потребовалось работать с сокетами напрямую — и опять, всё просто. TCP эхо-сервер пишется на коленке за пять минут, после прочтения документации. Да, документация — она на столько хороша, что docs.python.org на какое-то время выбился в мой личный топ самых посещаемых сайтов. Оттуда я почерпнул более глубокие знания о «нутрянке» Python’а — таких вещах, как слоты, дескрипторы, генераторы. Ни каких yield from
тогда ещё не было и впомине. Однако начали закрадываться смутные сомнения, что что-то не так…
Когда требовалась скорость, всегда находилась библиотека с нативными расширениями, и всё работало действительно быстро.
Потом была дейтсвительно большая система на Python. Не буду вдаваться в подробности, что за система, но она была дествительно большая. Сотни тысяч строк кода. Тысячи классов. Десятки взаимодействующих сервисов. API, очереди сообщений, SQLAlchemy. Ох и тормозило же всё это дерьмо)). Мы профилировали, дебажили, инструментировали, масштабировали — и всё равно тормозило. Что-то явно было не так. Тогда-то я и занялся исследованием проблемы GIL. Произовдительность сетевых сервисов можно было существенно повысить с помощь Linux’ового системного вызоваepoll
. Только вот была одна проблема… Видите ли, не возможно было обрабатывать отдельные соединения с помощью, скажем, пула потоков. Ну то есть как, возможно, но… Интерпретатор всё равно выполнял всегда один поток. Правда, если всё, что делает поток — это ждёт ввода/вывода или чего-то другого, то особых проблем это не вызывало. Ведь тогда ему дозволено отпустить глобальную блокировку. Но… Народ требовал хлеба и зрелищь! Ну не удобно, понимаешь, на каждый чих писать нативное расширение (отпускать блокировку имеют право именно они). Я же открыл для себя Tornado, Eventlet, Stackless Python (ныне почил), PyPy.
Я ещё больше углубился в «кишки» языка. Узнал мног интересного про особенности реализации. Как раз тогда и прозвучал первый звоночек. А именно, Python3000. Одна мысль не давала мне покоя — раз вы решились переписывать интерпретатор заново, умышленно ломая обратную совместимость — что мешало выпилить GIL к чертям собачим??? Но — не выпилили…
И вот, нынче только ленивый питонист не написал веб-сервис на asyncio. Его и ругают, и хвалят на все лады. Куча асинхронных фреймворков. Гвидо ушёл. Новые версии языка релизятся как горячие пирожки. Засилие моржей и type hint’ов.
Для меня же Python умер — как раз тогда, когда Гвидо ушёл. Пока он был, язык имел хоть какую-то концептуальную целостность. Сейчас же — это сливной бачок для любой модной фигни, которую тащат в язык не задумыааясь -, а нужна ли она там вообще? Чего только стоит запиливание pyenv — ничем не напоминает времена Ruby?
И всё же, Python уникален. Это одновременно и отличный язык, и ужасная реализация. Арминушка «наше всё» Роначер это понял значительно раньше — и свалил в Rust. Когда вы начинаете погружаться в исходники самого интерпретатора, к вам неизбежно приходит осознание того, на сколько плохо он реализован. Отсутствие спецификации также не идёт языку на пользу, а только сдерживает развитие альтернативных реализаций. Спецификация «just do what CPython does» — гарантия так себе.
Когда-то Python действительно был отличным языком. Он подходил и для быстрого прототипирования, и для не больших (да и для больших тоже) проектов любого толка — веб, десктоп, системные сервисы. Динамическая типизация не вызывала особых проблем. Это был целостный, предсказуемый язык. Сейчас же — это франкенштейн, разваливающийся на части. Смена поколений в менеджменте языка так же не пошла ему на пользу — хипстеры с NIH-синдромом явно не делают его лучше.
И всё-таки, это было отличное время! По крайней мере, для меня. Я благодарен Гвидо и всему сообществу Python за этот уникальный язык! Однако рано или позно приходит время двигаться дальше.
А вы как считаете?