#python python... PYTHON 🔛 🚀
11 subscribers
912 photos
7 videos
158 files
1.54K links
Download Telegram
The Well-Grounded Python Developer

Автор:
Doug Farrell
Год издания: 2023

#python #en

Скачать книгу
Forwarded from DE
Ребята, которые сделали ruff, выпустили свой тул для работы с зависимостями для python - uv. Они позиционируют его как замену pip, pip-tools и virtualenv. Написан на расте, поэтому работает быстро.

Также они взяли на себя дальнейшую поддержку rye (который изначально сделал Армин Ронахер, автор flask) и судя по всем планируют постепенно эти проекты объединить в один.

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

Анонс: https://astral.sh/blog/uv
Репозиторий проекта: https://github.com/astral-sh/uv
Forwarded from Хитрый Питон
Ребята, которые сделали ruff, выпустили свой тул для работы с зависимостями для python - uv. Они позиционируют его как замену pip, pip-tools и virtualenv. Написан на расте, поэтому работает быстро.

Также они взяли на себя дальнейшую поддержку rye (который изначально сделал Армин Ронахер, автор flask) и судя по всем планируют постепенно эти проекты объединить в один.

Выглядит вкусно, попробую поиграться с uv на пет-проектах.

Анонс: https://astral.sh/blog/uv
Репозиторий проекта: https://github.com/astral-sh/uv
Forwarded from РУССКИЙ КОД
🏛16 февраля с 18:00 до 19:45 состоятся три публичные лекции, посвященные языку программирования Python

Вы узнаете:
🟠Проблемы и решения в системах управления пакетами Python
🟠Новые идеи и подходы в web фреймворках
🟠Новый web фреймворк, о котором вы еще не слышали
🟠Как из исходного кода получается абстрактное синтаксическое дерево
🟠Какие оптимизации можно сделать статически
🟠Как из AST получается байткод
🟠Какие оптимизации есть на шаге выполнения байткода (Tier1, Tier2, JIT)
🟠Что такое C-API, и почему он настолько важен для CPython


📍Место: Лекторий Wink, павильон «Мир цифры» (ПАВИЛЬОН Е)
📌Вход свободный, регистрация не требуется.

До встречи❗️
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Антон Ширяев
Недавно вышел интересный проект pixi - https://prefix.dev/

Это проект от создателей Anaconda, направленный на устранение главного недостатка проекта - отсутствия воспроизводимости рабочего окружения.
Создатели пытались взять лучшее что есть в conda и poetry )

Был бы рад услышать комментарий "poetry vs pixi" =)
Forwarded from Хитрый Питон
Мы у себя в компании начали аккуратно переходить на новый менеджер пакетов uv (https://github.com/astral-sh/uv) и решил рассказать, как все идет.

Так как тула новая, пришлось ждать пока пофиксят 2 бага в которые мы упирались. После чего все равно не заработало, но проблема была уже на нашей стороне. Но самое главное, что после решения этих проблем все работает как часы уже вторую неделю 🙂

Все сложности были при использовании нескольких индексов:
- политика разрешения зависимостей uv отличается от pip - это важно, когда используется свой индекс в добавок к pypi
- авторы решили не переиспользовать переменную окружения PIP_EXTRA_INDEX_URL - для uv надо задавать UV_EXTRA_INDEX_URL
- в UV_EXTRA_INDEX_URL лушче прописывать `/simple`-индекс, у меня сначала было не так, pip работал, а uv уже нет

Но какая же uv офигенно быстрая. Вот примеры двух наших разных проектов:

1. Внутренняя библиотека (меньше 20 зависимостей)
- pip-tools 4 минуты 7 секунд
- с uv 10 секунд

2. Большой старый монолит на Django (больше 100 зависимостей):
- с pip-tools 18 минут 19 секунд
- с uv 32 секунды (!!!)

В общем я очень доволен результатом и рекомендую как минимум посмотреть на эту тулзу.
Forwarded from Записки kiriharu
В нашу жизнь проникает всё больше AI инструментов, поэтому делитесь в комментариях какими пользуетесь сами или о которых знаете.

Вот список из моих, юзаю практически каждый день:
- Очевидный ChatGPT
- Апскейлиг картиночек (старые мемы выглядят как новые!)
- Переводчик DeepL
- Поисковик Perplexity AI
- Нейросеть от Яндекса, которая кратко пересказывает содержимое статей и видео
- А вот тут мелкомягкие позволяют генерировать картиночки
- Вот тут я удаляю фон у фоточек
Forwarded from DE
👩‍💻 match/case

Для версий Python 3.10 и выше.

Деструктуризация с помощью образцов настолько выразительна, что иногда даже наличие единственной ветви case может сделать код проще. Гвидо ван Россум собрал коллекцию примеров match/case, один из которых назвал «Очень глубокий итерируемый объект и сравнение типа с выделением».

Это здорово, но меня больше поразил тот факт, что можно проверять типы и насколько выразительно это выглядит, ниже смотри пример.

❤️‍🩹 Классическая версия:
 def write_value(self, value):
if isinstance(value, str):
self.simple_element("string", value)

elif value is True:
self.simple_element("true")

elif value is False:
self.simple_element("false")

elif isinstance(value, int):
if -1 << 63 <= value < 1 << 64:
self.simple_element("integer", "%d" % value)
else:
raise OverflowError(value)

elif isinstance(value, float):
self.simple_element("real", repr(value))

elif isinstance(value, dict):
self.write_dict(value)

elif isinstance(value, (bytes, bytearray)):
self.write_bytes(value)

elif isinstance(value, datetime.datetime):
self.simple_element("date", _date_to_string(value))

elif isinstance(value, (tuple, list)):
self.write_array(value)

else:
raise TypeError("unsupported type: %s" % type(value))
🔥 Версия с использованием match/case:
 def write_value(self, value):
match value:
case str():
self.simple_element("string", value)

case True:
self.simple_element("true")

case False:
self.simple_element("false")

case int():
if -1 << 63 <= value < 1 << 64:
self.simple_element("integer", "%d" % value)
else:
raise OverflowError(value)

case float():
self.simple_element("real", repr(value))

case dict():
self.write_dict(value)

case bytes() | bytearray():
self.write_bytes(value)

case datetime.datetime():
self.simple_element("date", _date_to_string(value))

case tuple() | list():
self.write_array(value)

case _:
raise TypeError("unsupported type: %s" % type(value))
#python #casematch
Please open Telegram to view this post
VIEW IN TELEGRAM
Зачем нужно делать кастомную базовую Pydantic модель?

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

Наличие такой глобальной модели позволяет настраивать поведение всех моделей в приложении. Рассмотрю несколько кейсов, когда это может понадобится.

1) Контроль над входными данными.
Например, мы хотим округлять все поля которые называются price до трех знаков после запятой. Сделать это можно так:

class CustomBaseModel(BaseModel):
@root_validator()
def round_price(cls, data: dict) -> dict:
prices = {k: round(v, 3) for k, v in data.items() if k == "price"}
return {**data, **prices}

Валидаторы дают возможность изменять входящие данные, но это стоит использовать с осторожностью.

P.S.: В коментах подметили, что такой подход неявный, и я с этим согласен. Ничего не мешает для таких целей сделать ещё одну базовую модель (PriceRoundBaseModel), наследуясь от нашей базовой СustomBaseModel и использовать её там, где такое поведение необходимо.

2) Кастомый энкодер/декодер json.
Пакет json из стандартной библиотеки очень медленный. При необходимости ускорить сервис этот пакет в первую очередь пытаются заменить на что-то побыстрее.
Это происходит из-за того, что операций по (дe)сериализации json в приложении может быть много, и смена библиотеки, в этом случае, дает ощутимый прирост к общей скорости.

В pydantic есть 2 опции в конфиге, которые позволяют изменять поведение энкодера и декодера. Выглядит это так:

def orjson_dumps(v, *, default):
# orjson.dumps возвращает байты, поэтому нам надо их декодить, чтобы соответствовать сигнатуре json.dumps
return orjson.dumps(v, default=default).decode()

class CustomBaseModel(BaseModel):
class Config:
json_loads = orjson.loads
json_dumps = orjson_dumps

#pydantic
Как запускать синхронные функции в асинхронном роуте FastAPI?

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

Решений, как это сделать, на самом деле много. Самый простой вариант, который предоставляет FastAPI (а если быть точнее - Starlette, который использует anyio) - функция run_in_threadpool, которая запустит синхронный код в потоке:

@app.get("/")
async def my_router():
result = await service.execute()
client = SyncClient()
return await run_in_threadpool(client.execute, data=result)

Кстати, BackgroundTask использует тот же самый способ, только он не возвращает результат выполнения.

А как бы вы решали/решаете такую проблему? Пишите в комментариях 😎 !

#fastapi #anyio
Релиз FastAPI 0.100.0🔥

Себастьян закончил обновление pydantic-а. Теперь можно насладиться звуком ржавчины и приростом скорости при переходе на новую версию FastAPI.

Чейнжлог совсем небольшой получился
https://fastapi.tiangolo.com/release-notes/#01000

p.s. в ближайшее время доберусь до чейнжлога pydantic v2 и сделаю обзорный пост
GIL скорее всего уберут из Python!

Руководящий совет объяснил статус PEP 703 (сделать GIL опциональным). Если кратко, то понятно следующее:

— Они намерены принять PEP 703, но всё ещё работают над деталями, предстоит много работы.
— Вероятно, лет через пять сборка без GIL будет ЕДИНСТВЕННОЙ сборкой, так как они не хотят разделять комьюнити на no-GIL и GIL.
— Совет не хочет повторения ситуации с Python 3, поэтому большое внимание будет уделено обратной совместимости.
— Прежде чем отказаться от GIL, они внимательно будут изучать работу комьюнити в этом направлении. Ребята хотят убедиться, что переход будет плавным, а поддержка режима no-GIL будет достаточна.
— Не смотря на все это, совет хочет иметь возможность "дать заднюю", если для комьюнити и языка это принесёт намного больше проблем, чем профита.

Новость просто невероятная. Остается надеяться на комьюнити, будет ли оно готово адаптировать свои библиотеки под этот режим?

#gil
Появился PEP 723, который предлагает "встраивать" pyproject.toml в однофайловые скрипты.
Предлагается добавить переменную __pyproject__, которая будет содержать в себе валидный TOML, описывающий метадату скрипта, в том числе как скрипт запускать и какие зависимости необходимы для запуска.

К примеру, вот так будет выглядеть скрипт, которому для работы нужна библиотека requests и питон 3.11 или выше:

__pyproject__ = """
[project]
requires-python = ">=3.11"
dependencies = [
"requests<3",
]
"""
import requests
resp = requests.get("https://peps.python.org/api/peps.json")
print(resp.json())

PEP прикольный, что-то такое есть в качестве экспериментального RFC в Rust. Из минусов хотел бы отметить то, что автоматическая установка зависимостей может привести к запуску нежелательного кода. Но решение банальное - перед тем как что-то запускать, проверяйте, что вы запускаете.

#pep
Недавно мой знакомый @nesclass (можете ему писать по теме доклада) выступал c докладом "Асинхронное варение MongoDB в Python" на Pytup.

Автор объяснил наглядно в чем различие реляционных баз от документно-ориентированных, немного рассказал про подходы работы с БД, затронул тему object mapper'ов и много рассказал про Beanie - ODM для работы с MongoDB (про которую я писал) и саму монгу.

Доклад отлично подойдет для тех, кто хочет ознакомиться с этим инструментом и послушать про подводные камни, с которыми часто встречаются новички.

#посмотреть
Если вам приходилось работать с bash, например парсить логи, вы наверняка видели или использовали команды следующего вида:

cat app.log | grep 'exception' | awk '{ print $2 }'

Здесь мы последовательно считываем содержимое файла app.log, фильтруем по подстроке exception и выводим вторую колонку.
Символ |, которая разделяет команды называется "пайпом" - он перенаправляет вывод из одной команды в другую, а вся эта конструкция в целом называется конвейером, и она очень часто используется в функциональном программировании.

В Elixir есть оператор конвейера |> который позволяет передавать результат выполнения левого выражения в правое. Это позволяет делать вот такие штуки:

1..10 
|> Enum.map(fn x -> x * 2 end)
|> Enum.filter(fn x -> x > 10 end)
[12, 14, 16, 18, 20]

Здесь мы генерируем список от 1 до 10, умножаем каждый элемент на 2 и фильтруем только те, которые больше 10.
Согласитесь, так удобнее работать с коллекциями, особенно там где данных много и их хочется как-то отфильтровать. В случае использования конвейеров нам больше не надо строить громоздкие циклы, а код прост и понятен.

Если вам интересно. как можно сделать такое в Python, то для вас есть библиотека Pipe. Реализация очень простая - библиотека добавляет класс Pipe который переопределяет оператор |. Далее мы оборачиваем наши функции в этот класс и можем строить конвейеры!

Например, вот так мы можем получить сумму товаров, цена которых больше тысячи:

from typing import NamedTuple
from pipe import select, where

class Product(NamedTuple):
name: str
price: int

products = [Product("choco", 123), Product("auto", 10000), Product("photo", 1200)]
sum(
products
| select(lambda product: product.price)
| where(lambda x: x > 1000)
) # 11200

#библиотека
На второе октября намечен релиз Python 3.12, поэтому Никита Соболев (opensource разработчик и контрибьютор в сpython) рассказывает про новинки в новой версии и чуть затрагивает то, что ожидает нас в 3.13.

Рекомендую посмотреть, чтобы оставаться в теме новых обновлений.

#посмотреть