Питонические атаки
1.27K subscribers
173 photos
3 videos
1 file
454 links
Всяческие заметки про программирование на Python и другие весёлые истории.
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
Смотрите какая штука. Умеет делать hot reloading для многих программ без потери состояния. То есть прям сохраняешь файл на диске, она догружает изменения прямо в работающую программу, что-то там до/перевычисляет до точки останова, и показывает тебе новый результат.

Можно использовать утилиту саму по себе, а можно интегрировать её в редактор. На данный момент есть плагин для PyCharm, а расширение для VSCode в статусе "coming soon". Запилена отдельная поддержка для Django, Flask, SQLAlchemy и Pandas. Вроде можно достаточно гибко управлять поведением reloading'а, чтобы обработать разные краевые случаи.

Выглядит круто!

https://reloadium.io/

P.S. С телефона гифку надо смотреть в оригинале, иначе шакалы.
Python 3.11.1 релизнулся — первая багфикс версия.

Есть такое суеверие, что лучше не обновляться на версию с нулевым последним числом, а подождать первого багфикс-релиза. Вот, теперь даже консервативные пользователи могут обновляться. Хотя, по моим ощущениям, и нулевая версия почти никаких проблем не доставляла (кроме отсутствия предсобранных колёс у библиотек).

Кстати, метрика поддержки 3.11 в библиотеках выросла до 25.6%. Месяц назад она была 19.4%.
FastAPI перегнал Django по количеству скачиваний? 🤔

Твит
PyPI обновился с 3.10 до 3.11 и стал потреблять в два раза меньше процессора.

Второй график — это сглаженная версия первого.

Твит
А слышали ведь про то, что ChatGPT умеет прикидываться bash’ем и успешно интерпретирует разные команды над файлами, запоминая при этом состояние? Похоже, эта нейросеть в целом довольно успешно может симулировать различные интерпретаторы. Python REPL тоже может, причем зачастую учитывает даже разные неочевидные детали. Ответы выглядят будто правильные, но не всегда таковыми являются, само собой, так что доверять такому интерпретатору нельзя.

https://mathspp.com/blog/running-python-inside-chatgpt
Команда форматтера black готовится к новому году обновлению дефолтного стиля. Они весь год собирали разные изменения/улучшения, но не включали их, чтобы лишний раз не тревожить код пользователей. И вот в начале 2023 года выйдет релиз, где всё это наконец вступит в силу. Готовьтесь, что после обновления black у вас изменится форматирование кода. Вероятно, это обновление лучше делать отдельно от других изменений, чтобы не заставлять ваших ревьюверов вычитывать смысловые изменения в коде вперемешку с изменениями в форматировании.

Список изменений можно почитать в блоге одного из разработчиков: https://ichard26.github.io/blog/2022/12/black-23.1a1/

#black #formatter
Если хотите попробовать новый стиль уже сейчас, то это приветствуется и делается через установку превью-версии:

python -m pip install black==23.1a1

На одном из рабочих проектов форматирование новой версией завершилось вот с таким результатом, то есть изменилось ~5% файлов:

274 files reformatted, 4738 files left unchanged.

Большая часть изменений — это вырезанная первая пустая строка в определениях функций и классов. Пожалуй, хорошо, что форматтер стал за этим следить, а то эти пустые строки воспринимались как что-то лишнее. Кто, блин, их вообще ставит?

Многие изменения я словить не смог, но они должны быть весьма приятными. Например, форматтер вместо разгибания тайп-хинта по какой-то произвольной скобке:

def frobnicate() -> ThisIsTrulyUnreasonablyExtremelyLongClassName | list[
ThisIsTrulyUnreasonablyExtremelyLongClassName
]:
pass

Научился группировать и делать более осмысленные переносы:

def frobnicate() -> (
ThisIsTrulyUnreasonablyExtremelyLongClassName
| list[ThisIsTrulyUnreasonablyExtremelyLongClassName]
):
pass

#black #formatter
Forwarded from Хитрый Питон
Вышел релиз SQLAlchemy 2.0, получается довольно интересно:

- Полная поддержка типов: ORM-модели теперь можно делать полностью типизированные, результаты запросов тоже типизированы
- Теперь ORM-модели можно объявлять как MappedAsDataclass и в этом случае на выходе получатся полноценные датаклассы
- Для массовых добавлений/изменений вместо bulk_* методов теперь можно использовать insert-ы и update-ы, которые стали достаточно умными, чтобы делать это одним запросом и поддерживать .returning()
- C-расширения переписали на Cython и обещают повышение их производительности
- Поддержка нового psycopg3 (aka "просто psycopg")

Резюмируя - очень здорово, что в довольно "олдскульный" SQLAlchemy затащили поддержку всяких современных фич языка. Будет интересно попробовать это все.

Статья про изменения в 2.0 https://docs.sqlalchemy.org/en/20/changelog/whatsnew_20.html
QuickStart, в котором показан новый подход к объявлению моделей https://docs.sqlalchemy.org/en/20/orm/quickstart.html
В Python 3.12 планируют переделать f-строки в рамках PEP 701 – Syntactic formalization of f-strings.

Дело в том, что f-строки в язык занесли в версии 3.6, когда балом правил еще старый LL(1) парсер, который было сложно расширять, поэтому для f-строк был написан отдельный маленький парсер. Из-за этого они получились слегка неполноценными, а еще в этом отдельном парсере, само собой, были отдельные новые баги. Самое яркое ограничение — это то, что внутри f-строк нельзя использовать те же кавычки, в которых лежит сама строка. Это ж капец как неудобно, что приходится другие кавычки использовать, чтобы просто достать что-то из словаря. У меня линтер на это ругается, и приходится ему каждый раз объяснять, что тут красиво никак не сделать.

Вот, в 3.12 разбор f-строк доверят основному PEG-парсеру, а сам синтаксис f-строк станет частью грамматики языка. Можно будет использовать любые кавычки, которые нравятся. А еще бесконечно вложенные f-строки. Не знаю, зачем нам это, но хорошо, что станет можно. Жду 3.12.
Forwarded from Хитрый Питон
Вышел MyPy 1.0.0, из интересных изменений:

- На 40% быстрее, я очень рад, потому что на более-менее большой кодовой базе он раньше тормозил как не в себя
- Добавили сообщения о undefined variables, использовании переменной до ее объявления. Кажется, тот же flake8 нормально это отлавливает, но все равно выглядит небесполезно
- Добавили поддержку типа Self (есть в 3.11, для более ранних версий надо использовать typing_extensions)
- Реализовали поддержку ParamSpec, но я если честно еще ни разу ParamSpec не использовал в реальном коде, но если интересно, это PEP 612

И еще из интересного, они на конец перешли на semver и теперь будет проще по номерам версий понимать, будут ли подводные камни при обновлении 🙂

Подробнее вот тут https://mypy-lang.blogspot.com/2023/02/mypy-10-released.html
Ещё про изменения в Python 3.12. Недавно приняли PEP 698 – Override Decorator for Static Typing.

Идея простая. Часто в коде переопределяются методы родительских классов, но происходит это сейчас неявно. То есть когда всё хорошо, то тайп-чекер видит, что у родителя есть метод Parent.foo(), у ребёнка есть метод Child.foo(), они называются одинаково, а значит один переопределяет другого. Но вот когда что-то начинает меняться (например, Parent.foo() переименовывается или удаляется, а Child.foo() почему-то остаётся нетронутым), то для тайп-чекера уже не очевидно, что эти два метода как-то были между собой связаны. К сожалению, тайп-чекер видит только нынешнее состояние кодовой базы и не знает с какой стороны мы в это состояние пришли. Короче, есть риск выполнить рефакторинг наполовину, потеряв связи между родителями и детьми, из-за чего много чего может пойти не так, а тайп-чекер просто не увидит проблемы.

В PEP 698 добавляется декоратор @typing.override, который показывает, что отмеченный метод класса является переопределением одноимённого метода родителя. Если у родителя нет такого метода, то тайп-чекер заметит ошибку — хотели что-то переопределить, но только вот непонятно что. Придётся идти и чинить, приводить код в согласованное состояние.

Использование декоратора позволяет тайп-чекеру глубже понимать намерения в коде и вводить дополнительные проверки, но это всё дело добровольное. Без декоратора всё будет работать как прежде. В рантайме декоратор по традиции ни на что не влияет.

Примечательно, что авторы инициативы все из Фейсбука, и пробную имплементацию они тоже занесли в свой фейсбучный тайп-чекер pyre. Похоже, у них там наболело.
Про ruff (1/5)

Несколько месяцев назад:
Что за ruff вообще такой? Линтер? Вижу ридми, обильно приправленный шильдиками и эмодзи, какие-то взрывающие мозг ⚡️бенчмарки⚡️, светло-коричневая полосочка на гитхабе, слышу рёв легионов воинов-фанатиков из твиттера. Погодите, да это же... Да, я определённо такое уже видел. Так происходит каждый раз, когда адепт Rust 🦀 отвлекается на минуту от разбрасывания какашек в комментах про новости о любом другом ЯП и садится что-нибудь переписывать. Это старо как мир. Вот хоть раз это переписанное смогло заменить оригинал? Да, здорово, что есть классные сияющие bat и ripgrep, но всё равно ведь все пользуются дефолтными cat и grep, которые ещё каменным молотом на перфокарте выбивали. Нафига мне переписанный клон линтера, если у меня есть оригинал и он хорошо справляется со своей работой? Да и наверняка, оно неюзабельное и вообще все просто похайпят и забудут через месяц, как обычно. Да и переписали, конечно, не точь-в-точь, а с какой-нибудь неочевидной разницей. Мне вот оно надо в этом разбираться? У меня работы полно. Ага, ну вот, плагины не поддерживаются. Какой может быть нормальный линтер без плагинов? Здорово, что быстрый, но он же нифига не умеет. Короче, это всё информационный шум, пустое.

На прошлой неделе:
Так, чёт много упоминаний. Был недавно на конференции EkbPy, там ruff на слайдах упоминался минимум дважды. Хм, смотрю, прогрессивные FastAPI и pydantic уже выкинули другие линтеры и вкрутили себе ruff в CI. Вижу, TalkPython записали выпуск подкаста про этот тул, а JetBrains собираются записывать про него вебинар прямо в день всех влюбленных. Ого, 8.2к звёздочек на гитхабе — это больше, чем у flake8 и pylint вместе взятых. Репозиторий существует всего полгода, вы вообще когда успели-то? Да даже уже в каналах с мемесами начали про него писать. Да почему все так влюбились в этот линтер? Придётся ставить. Дальше это игнорировать уже нельзя.

И я поставил. Запустил. Блин. А как записаться в легион фанатиков?
Про ruff (2/5)

Если кто ещё не знает, то ruff — это очень быстрый линтер для Python, написанный на Rust.

Давайте начнём разбираться по порядку — сначала про набор правил и про их качество.

С дефолтными настройками ruff повторяет функционал flake8. Вообще, в этом линтере довольно много идей унаследовано именно из flake8, например, настройки очень похожи, названия правил совпадают один к одному. Похоже, ruff позиционируется в первую очередь как замена flake8 — у них даже тулза для миграции есть, которая переносит все настройки.

Но, кроме дефолтных правил flake8, в комплекте уже заимплеменчена куча различных других правил, которые повторяют значительную часть популярных плагинов для flake8, вообще имплементации просто каких-то других инструментов, а также есть немного своих собственных правил. Да, в ruff уже в комплекте есть большинство правил из pylint, есть сортировщик импортов, который фактически заменяет isort, есть mccabe, bandit, pyupgrade. Из того, что я люблю тут есть flake8-bugbear, flake8-pytest-style, flake8-logging-format и другие хорошие плагины. Это всё уже прям встроено внутрь ruff, нужно лишь включить эти правила в конфиге. И да, это всё написано на Rust, как и сам линтер. Автор настолько упоролся, что переписал заново кучу популярных плагинов на другом языке, и он продолжает это делать постоянно. Сейчас у ruff в сумме уже около 400 правил и 44 набора правил. Велика вероятность, что здесь уже есть всё, чем вы пользуетесь. Либо это здесь совсем скоро появится, учитывая скорость развития инструмента.

Я взял большой рабочий проект примерно на 500к строк кода (это много) и запустил на нём flake8 и ruff, предварительно их чуть поднастроив (увеличил длину строки, отключил некоторые правила, которые противоречат black). Результат запуска видно на скрине ниже. Вывод у двух утилит почти идентичен, кроме лишь того, что ruff вставляет в вывод звёздочки [*], про которые я отдельно расскажу чуть позже.

Сумма ошибок слегка не сходится — flake8 находит больше проблем. Предполагаю, что это потому что правило E501 в ruff работает по принципу black, а не строго, как в оригинальном flake8. То есть ruff позволяет слегка выходить за ограничение по длине строки так же, как это делает black. Линтер заточен именно под использование в связке с black. Они даже не стали имплементить большинство проверок, связанных с неправильной расстановкой пробелов, потому что в наш век автоформаттеров эти правила уже не имеют никакого смысла. Этими пробелами в коде всё равно управляет не человек. Ещё ruff потерял несколько ошибок в других правилах, но тут я даже хз. Мне лень искать эти несколько потерянных ошибок среди сотен найденных.

Вердикт: недостатка правил тут точно нет, есть небольшая разница в том, как правила работают. Критична ли эта разница? Для меня скорее нет.
Скриншот со статистикой работы flake8 и ruff.
Про ruff (3/5)

Теперь про скорость. Действительно ли ruff такой быстрый?

На том же проекте на 500к строк кода (это много) на моей машине ванильный flake8 заканчивает работу примерно за 6.2 секунды, потребляя при этом 700% cpu. То есть он попытался отожрать почти все ядра. Вывод линтера я отправляю в /dev/null, чтобы измерять именно работу линтера, а не время печатания простыни ошибок в stdout. Перезапускаешь линтер — и снова те же самые 6.2 секунды, потому что во flake8 нет никакого кэширования, он каждый раз делает всё заново.

Запуск ruff занимает 0,42 секунды и потребляет примерно 500% cpu. Оп, в 15 раз быстрее, проца использует меньше. Второй запуск ruff занимает уже всего 0,1 секунды, потому что он берёт все результаты из кэша. Оп, в 62 раза быстрее. Если поменять один файл, то ruff пересчитает этот один файл, а все остальные результаты всё равно возьмёт из кэша, и суммарное время будет те же 0,1 секунды.

А давайте теперь добавим несколько плагинов. Голый линтер нам же не особо интересен, да? Устанавливаю flake8-bugbear, flake8-logging-format, flake8-pytest-style. Количество ошибок от flake8 вырастает до 5443, а время работы до 9.4 секунды. Включаю эти же 3 набора правил в ruff. Количество ошибок 5648 (чёт разница увеличилась, странно). Время работы на холодную колеблется в интервале 0,4-0,6 секунд, а с прогретым кэшем отрабатывает стабильно за всё те же 0,1 секунды. Здесь разница по скорости уже почти в 100 раз, и это я добавил относительно лёгкие плагины. Добавляем ещё несколько плагинов, и flake8 уже работает дольше 20 секунд, а ruff примерно как и раньше. Вообще, скорость работы flake8 довольно быстро деградирует.

Почему он быстрее? Ну, во-первых, потому что написан на низкоуровневом языке, без жирных объектов в памяти и без сборки мусора. Во-вторых, не делает лишней работы — все проверки выполняются за один проход. Ровно одно чтение каждого файла, ровно один разбор AST/CST каждого файла, и на этом работают вообще все проверки внутри тулзы (и не только проверки, читай дальше). В противовес, модульному flake8 зачастую приходится делать эту же работу несколько раз, потому что некоторым проверкам недостаточно просто AST дерева, им приходится самостоятельно читать и разбирать файлы, чтобы вычленить больше информации. В-третьих, здесь сразу сделали кэш. Блин, это же очевидная оптимизация. Почему во flake8 этого до сих пор нет?

Мелочь ли это? Ну хз. Я за 20 секунд успеваю заскучать и переключиться в телегу, что практически гарантировано выключит меня из состояния потока. И уж точно я буду стараться запускать этот медленный линтер как можно реже, а значит буду получать меньше обратной связи. С другой стороны, ruff можно запускать хоть на каждую новую строчку кода. У него даже есть режим --watch, когда он висит в фоне и перезапускает проверки на каждое изменение.
Про ruff (4/5)

Помните я упоминал про звёздочки в выводе ruff? После всех ошибок внизу есть ещё сноска, которая объясняет эти звёздочки:

Found 1986 errors.
[*] 1209 potentially fixable with the --fix option.

То есть можно запустить ruff check --fix и он не просто отрепортит ошибки, он сам ещё и пофиксит большую часть из них. Ни flake8, ни pylint так делать не умеют. Автор ruff очень упорот. Он не просто переписал все эти 400 правил с Python на Rust, но он ещё и научил свой линтер фиксить эти ошибки. Насколько вижу, примерно половина правил имеют эту звёздочку. Это. Просто. Офигенно.

Да, в этом режиме он сам выкинет неиспользуемые импорты, сам отсортирует импорты по алфавиту. Получается, что isort уже можно не запускать, а это минус несколько секунд из пайплайна. Полноценно форматировать код ruff пока не научился, но у них есть амбиция заменить собой даже black. И я почему-то верю, что у ruff получится. Это реально какой-то комбайн-мультитул, который всасывает в себя всё больше разных инструментов, причём попутно делая их быстрее и лучше. Автор тулзы уже и про тайп-чекинг тоже задумывается.

Вы всё ещё думаете, что ваш нынешний линтер хорошо делает свою работу? А я вот уже не уверен. Я определенно пересмотрел свои ожидания от линтера. ruff просто задает новую планку. В хорошее влюбляешься очень быстро.
Про ruff (5/5)

Давайте и про минусы тоже поговорим. Не бывает же всё только хорошо.

1. Нет поддержки структурного паттерн-матчинга из 3.10. Линтер просто не понимает эту синтаксическую конструкцию. Так что если вы прогрессивные и у вас уже весь код на match-case, то вам пока придётся подождать. Хотя я слышал про людей, которые просто отказались от match-case как раз из-за ruff — преимущества линтера перевесили пользу от паттерн-матчинга. Линтер использует парсер из RustPython — это такой интерпретатор Python, написанный на Rust, проект-долгострой. Только парсер, сам интерпретатор не используется. А у RustPython есть отставание от CPython по фичам и поддерживаемому синтаксису.

2. Написано на Rust. Это не только плюс, но и минус. Так просто код почитать уже не зайдёшь, баг-фикс левой пяткой не отправишь. Тут думать придётся, Rust учить, а это довольно высокий порог входа и крутая кривая обучения. Автор, конечно, максимально дружелюбен, и приглашает всех приходить и делать фиксы, даже если вы только-только начали учить язык и не уверены в правильности подходов. За плохой код обещает не гнобить, оказывать всяческую моральную поддержку. Он сам питонист и далеко не эксперт в расте, и это вообще его первый серьёзный проект.

3. Написано на Rust. Как рядовой пользователь, вы этого скорее всего даже и не заметите, потому что линтер легко устанавливается через pip, есть предсобранные колёса для всех популярных платформ, включая даже Alpine Linux. Но если вам вдруг повезло пользоваться чем-то менее мейнстримным, то будьте готовы ставить весь тулчейн Rust и собирать линтер из исходников. Хотя, у вас, наверное, и без того жизнь сложная. Линтер какой-то скомпилировать — это мелочь.

4. Нет системы плагинов, пока что. Сейчас автор сконцентрирован на том, чтобы затащить как можно больше уже существующих правил внутрь тулзы. Но он отдаёт отчёт, что все на свете проверки заимплементить невозможно, и нужно дать юзерам возможность иметь свои кастомные правила, которые не будут жить внутри ruff. Говорит, что можно будет писать свои правила как на расте, так и на питоне. Звучит-то хорошо, но я не понял, как он собирается это сделать. И не начнёт ли от этого сильно проседать скорость работы? Посмотрим.

5. Проект все ещё на очень ранней стадии. Новые релизы выкладывает почти каждый день, и каждый из них потенциально несёт в себе ломающие изменения, потому что никаких гарантий обратной совместимости на этом этапе дать нельзя. Использовать только смелым и отчаянным. Когда исправят проблему с паттерн-матчингом, то сделают стабильный релиз.


Сначала я вообще не понял идею и был настроен очень скептически. А сейчас под впечатлением, что такую простую вещь, как линтер, можно, оказывается, сделать намного лучше. Ненавижу эти кликбейтные заголовки по шаблону "X — убийца Y?", но тут реально иначе и не скажешь. ruff точно закрепится в наборе инструментов рядового питониста и убьёт многих из своих конкурентов, если они срочно не прыгнут выше головы. Как выяснилось, убивать нынешние стагнирующие линтеры совсем не сложно.

Исходники и документация вот здесь: https://github.com/charliermarsh/ruff

Ставьте и делитесь впечатлениями!
И снова про ruff.

Чарли Марш — автор инструмента — видит логичным ходом впилить в ruff автоформаттер, чтобы можно было запустить ruff --fix и пофиксить все стилистические проблемы, и стало красиво. Вот здесь в ишью уже пришли на обсуждение и мейнтейнеры black, и мейнтейнеры blue (это форк black с одинарными кавычками), кто-то предлагает взять yapf за ориентир, а Чарли просто отчитывается, что уже начал работу, и его автоформаттер частично проходит тест-сьют из black.

Вчера он влил первую пачку изменений. Для пользователей форматтер ещё не доступен, но внутрянка уже подготавливается. В PR перечислено, что уже работает, а что нужно ещё доделать. Это я к тому и пишу, что он, блин, правда начал это делать, и я удивлён. Просто помню, как мучительно black полтора года стабилизировал "магические запятые", и они всё время то появлялись, то исчезали, что в моей голове уже сложилось впечатление, что заново этот путь никто не захочет пройти. Но нет, нашлись отчаянные.

> I'd like the autoformatter to be a little more flexible than Black, which would in theory make it a suitable replacement for Blue too.

И, кстати, наверняка, в этом форматтере будут настройки стиля. Может, не как в yapf, но как минимум можно будет выбрать стиль кавычек. Что с одной стороны хорошо и удобно, а с другой стороны может снова спровоцировать конфликт между племенами байкшеддеров. Ох.

Всё-таки удивительно, как быстро ruff развивается. Люди годами делали эти инструменты, а он создаёт их копии за считанные недели. И, блин, наверняка же сделает. В чём секрет, как думаете?
В чате-комментах сообщают, что Pydantic поднял бабла 💸

Теперь это не просто библиотечка для парсинга/валидации данных. Это теперь вообще-то корпорация Pydantic Services с автором библиотеки, Samuel Colvin, во главе! Новоиспечённый стартап получил 4.7 миллиона долларов венчурного капитала в рамках seed-раунда. Основным инвестором является знаменитый фонд Sequoia Capital, про который даже я почему-то слышал, хотя я довольно дремуч. Выглядит супер-круто на фоне общего экономического кризиса.

Как я понял, Сэм пока вообще единственный член команды, но на полученные деньги собирается быстро нанять себе ещё несколько крутейших разработчиков, в основном из числа контрибьюторов в библиотеку. По плану, сначала он хочет выпустить Pydantic V2, переписанный на Rust и ускоренный в 17 раз, а затем делать что-то связанное с улучшением DX (developer experience) в облачных технологиях, но что конкретно — не говорит, тайна. А опенсорсный Pydantic будет краеугольным камнем всех остальных разработок компании.

Офигенно, что у Pydantic теперь будет целая команда фулл-тайм разработчиков. Очень любопытно, как они будут монетизироваться. Инвесторы, к сожалению, не ради звёздочек на гитхабе деньги раздают.

Тут пост в блоге Pydantic, а здесь новость на TechCrunch.