Питонические атаки
1.19K subscribers
183 photos
4 videos
1 file
459 links
Всяческие заметки про программирование на Python и другие весёлые истории.
Download Telegram
А ещё в 3.12 в очередной раз улучшат сообщения об ошибках. Интерпретатор научится догадываться о забытых импортах модулей из стандартной библиотеки, а также подсказывать про забытый self.

Взял отсюда и отсюда.
👍17🤔2
О, кстати, прикол. Не задумывался, что лямбда-функции тоже можно аннотировать. Делать я так, конечно, всё равно не буду.

Твит здесь.
❤‍🔥131🥰1
Свежие драмы из интернета.

На днях flake8 переехал на GitHub. Они довольно долго были чуть ли не единственным известным мне проектом, который принципиально хостился на GitLab.

Точнее, переехали они уже полтора года назад, а на днях они удалили свой старый репо на GitLab, который в последнее время был лишь зеркалом. И тут все внезапно заметили этот переезд, потому что у кучи народа отвалились pre-commit хуки локально и начали падать проверки в CI. Напомню, что pre-commit устанавливает свои тулзы именно из git-репозитория по адресу, а не из PyPI по имени пакета. И хоть исправление этой проблемы — это всего лишь поправить 2 символа в ямле, и автор заранее везде, где только можно, анонсировал этот переезд, и даже написал скрипты, которые всё пофиксят автоматически, всё равно мало кто узнал об этом событии заранее. Неприятно получилось, и народ начал роптать.

Мейнтейнер обеих утилит — flake8 и pre-commit (да, их обе поддерживает один человек, и он же поддерживает ещё кучу всего) — рассказал в комментах на реддите, чем был мотивирован этот переезд. Оказывается, причиной послужил неприятный инцидент с криптомайнером, который каким-то необъяснимым образом был запушен каким-то левым чуваком в репо flake8 на гитлабе. Поддержка гитлаба ушла в отрицание и помогла примерно никак: "мы ничего не знаем, вы сами виноваты". Вот 🤷‍♂️

Если используете pre-commit, то проверьте у себя адрес к репо flake8. Запуск pre-commit autoupdate должен по идее всё автоматически обновить правильным образом.
👍20🤔4👏2🖕1
Forwarded from Python etc
I often find myself writing a context manager to temporarily change the current working directory:

import os
from contexlib import contextmanager

@contextmanager
def enter_dir(path):
old_path = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(old_path)


Since Python 3.11, a context manager with the same behavior is available as contextlib.chdir:

import os
from contextlib import chdir

print('before:', os.getcwd())
# before: /home/gram
with chdir('/'):
print('inside:', os.getcwd())
# inside: /
print('after:', os.getcwd())
# after: /home/gram
👍20😱32🎉1🖕1
Большое интервью Гвидо ван Россума час назад вышло у Лекса Фридмана

https://www.youtube.com/watch?v=-DVyjdw4t9I

0:00 - Introduction
0:48 - CPython
6:01 - Code readability
10:22 - Indentation
26:58 - Bugs
38:26 - Programming fads
53:37 - Speed of Python 3.11
1:18:31 - Type hinting
1:23:49 - mypy
1:29:05 - TypeScript vs JavaScript
1:45:05 - Best IDE for Python
1:55:05 - Parallelism
2:12:58 - Global Interpreter Lock (GIL)
2:22:36 - Python 4.0
2:34:53 - Machine learning
2:44:35 - Benevolent Dictator for Life (BDFL)
2:56:11 - Advice for beginners
3:02:43 - GitHub Copilot
3:06:10 - Future of Python

#IT #Python
🔥19👍3
В Golang 👣 есть такая инструкция defer, которая планирует отложенное действие при выходе из текущей функции. Часто этим пользуются как контекстным менеджером, типа, открываешь файл и тут же при помощи defer планируешь его закрытие:

f := createFile("/tmp/defer.txt")
defer closeFile(f)

Причём закрытие файла выполнится даже если где-то дальше в этой функции произойдёт ошибка — это предотвращает утечку ресурсов. Ещё при помощи defer можно, собственно, перехватывать и обрабатывать разные ошибки. Короче, да, примерно как контекстные менеджеры или блоки try-finally, но не создают дополнительный уровень вложенности в коде, а ещё открытие и закрытие ресурса обычно находятся в коде рядом друг с другом, а не на разных концах файла. Можно выполнить несколько defer — они складываются в стэк, а при завершении функции по очереди снимаются со стэка и выполняются (получается, в обратном порядке).

К чему я это. Чувак с реддита сделал аналог такой инструкции для питона. Работает следующим образом:

@defers
def f():
print(1)
defer: print(3)
print(2)

Вызов f() напечатает 1 2 3. Почти как на Go, только с декоратором над функцией и лишним двоеточием после defer.

Под капотом там происходит разбор и модификация AST тела функции, задекорированной
@defers
. Обратите внимание на строчку
defer: print(3)
. Синтаксически здесь происходит аннотация переменной defer, а в тайп-хинте лежит какой-то вызов функции. Python игнорирует тайп-хинты для переменных в теле функций, то есть функцию вызывать он не будет даже пытаться — можно положить туда что угодно, лишь бы соответствовало синтаксису. Библиотека выполняет код из тайп-хинта на выходе из функции. Интересная эксплуатация особенностей языка!

Автор не рекомендует пользоваться этим в продакшене. Это скорее забавная поделка, чем рабочий инструмент. Но если всё-таки будете, то обязательно применять в комплекте с:

result, err = do_thing()
if err is not None:
return None, err

Иначе не прочувствуете вайб! 🖥

GitHub | Тред на реддите
Please open Telegram to view this post
VIEW IN TELEGRAM
🤡20😁10👍7🔥32👎1🥴1
Я всё чаще и чаще замечаю Rust рядом с Python...

Совершенно недавно я нашел вот такой HTTP сервер на Rust для приложений на Python - Granian.

Разработчики ставят перед собой следующие цели:
+ Поддержка HTTP версий 1, 2 и 3
+ Один пакет для всех платформ
+ Сервер должен заменить Gunicorn/Uvicorn
+ Обеспечение большей производительности по сравнению с конкурентами.

Сейчас оно умеет в:
+ ASGI/3 и RSGI
+ HTTP/1 и HTTP/2
+ Вебсокеты над HTTP/1 и HTTP/2
+ Поддержка SSL

К сожалению проект пока что в супер-бетке, поддерживает Питон 3.7/3.8. Очень надеюсь что с этого что-то вырастет.

#библиотека
👍161👎1🤔1
Forwarded from Python etc
The typing.assert_type function (added in Python 3.11) does nothing in runtime as most of the stuff from the typing module. However, if the type of the first argument doesn't match the type provided as the second argument, the type checker will return an error. It can be useful to write simple "tests" for your library to ensure it is well annotated.

For example, you have a library that defines a lot of decorators, like this:

from typing import Callable, TypeVar

C = TypeVar('C', bound=Callable)

def good_dec(f: C) -> C:
return f

def bad_dec(f) -> Callable:
return f


We want to be 100% sure that all decorators preserve the original type of decorated function. So, let's write a test for it:

from typing import Callable, assert_type

@good_dec
def f1(a: int) -> str: ...

@bad_dec
def f2(a: int) -> str: ...

assert_type(f1, Callable[[int], str]) # ok
assert_type(f2, Callable[[int], str]) # not ok
👍8💩41🔥1
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. С телефона гифку надо смотреть в оригинале, иначе шакалы.
🔥18👍6
Python 3.11.1 релизнулся — первая багфикс версия.

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

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

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

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

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

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

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

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

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
👍18🤔1
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
🔥25
В 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.
👍31🍾6👏2