Shielded execution в asyncio
Допустим, есть следующий обработчик, который производит оплату:
Поможет нам в этом
Допустим, есть следующий обработчик, который производит оплату:
async def handler(request):Если соединение отвалится то обработчик упадет с ошибкой, так как серверу будет некуда отправлять ответ. Задача должна отмениться, но что если мы хотим, чтобы она выполнилась наверняка?
await service.pay(request.user)
return web.Response(text="payed")
Поможет нам в этом
asycio.shield()
. Он защищает задачу от отмены, даже в случае возникновения ошибки. Выглядит это следующим образом:async def handler(request):#asyncio #std
await asyncio.shield(service.pay(request.user))
return web.Response(text="payed")
❤4🔥1
Про __slots__
Python, аналогично другим динамическим языкам, таким как JavaScript, предоставляет возможность манипулирования объектами в рантайме, в том числе позволяет добавлять, изменять и удалять атрибуты. Цена этого – понижение скорости доступа к атрибутам и дополнительные расходы памяти.
Такое поведение нужно не всегда. Бывают случаи, когда мы точно знаем, какие атрибуты будут у наших экземпляров классов. Или же мы хотим ограничить добавление новых атрибутов. Именно для этого и существует
Слоты задаются через атрибут
В свою очередь, память экономится из-за того, что у класса не создается
#std #slots
Python, аналогично другим динамическим языкам, таким как JavaScript, предоставляет возможность манипулирования объектами в рантайме, в том числе позволяет добавлять, изменять и удалять атрибуты. Цена этого – понижение скорости доступа к атрибутам и дополнительные расходы памяти.
Такое поведение нужно не всегда. Бывают случаи, когда мы точно знаем, какие атрибуты будут у наших экземпляров классов. Или же мы хотим ограничить добавление новых атрибутов. Именно для этого и существует
__slots__
.Слоты задаются через атрибут
__slots__
в классе:class SlotsClass:Теперь мы не можем добавлять новые атрибуты к нашим объектам. Скорость доступа к атрибутам повышается на 25-30%, потому что при доступе к ним их больше не надо вычислять.
slots = ('foo', 'bar')
>>> obj = SlotsClass()
>>> obj.foo = 5
>>> obj.foo
# 5
>>> obj.another_attribute = 'test'
Traceback (most recent call last):
File "python", line 5, in <module>
AttributeError: 'SlotsClass' object has no attribute 'another_attribute'
В свою очередь, память экономится из-за того, что у класса не создается
__dict__
, который как раз хранил атрибуты.#std #slots
🔥7🤔1
Коробка с питоном
Про __slots__ Python, аналогично другим динамическим языкам, таким как JavaScript, предоставляет возможность манипулирования объектами в рантайме, в том числе позволяет добавлять, изменять и удалять атрибуты. Цена этого – понижение скорости доступа к атрибутам…
__slots__ и наследование
Важно помнить, что при попытке унаследовать класс с
Из-за этого возникает неоднозначность, какой именно слот использовать в результирующем классе.
#std #slots
Важно помнить, что при попытке унаследовать класс с
__slots__
подкласс их унаследует, но так же и создаст __dict__
для новых атрибутов:class SlotsClass:Это стандартное и понятное поведение. Чтобы избежать создания
__slots__ = ('foo', 'bar')
class ChildSlotsClass(SlotsClass):
pass
>>> obj = ChildSlotsClass()
>>> obj.__slots__
# ('foo', 'bar')
>>> obj.foo = 5
>>> obj.test = 3
>>> obj.__dict__
# {'test': 3}
__dict__
, можно снова переопределить __slots__
в подклассе:class SlotsClass:А что с множественным наследованием?
__slots__ = ('foo', 'bar')
class ChildSlotsClass(SlotsClass):
__slots__ = ('baz',)
>>> obj = ChildSlotsClass()
>>> obj.foo = 5
>>> obj.baz = 6
>>> obj.something_new = 3
AttributeError: 'ChildSlotsClass' object has no attribute 'something_new'
class ClassA:Оно не работает. Потому-что каждый класс может иметь свои собственные
__slots__ = ('foo', 'bar',)
class ClassB:
__slots__ = ('baz',)
class C(ClassA, ClassB):
pass
TypeError: multiple bases have instance lay-out conflict
__slots__
, которые могут пересекаться с другими классами, а это может привести к тому, что объекты могут быть созданы неправильно или будут иметь непредсказуемое поведение. Из-за этого возникает неоднозначность, какой именно слот использовать в результирующем классе.
#std #slots
🔥5
Интересный доклад, в котором разработчик из Uchi.ru рассказывает, как они строили realtime аналитику. Внутри доклада Kafka, Redis, Postgres и, внимание, Django.
#посмотреть #django
#посмотреть #django
YouTube
Real-time аналитика в Uchi.ru - как смотреть сложные метрики здесь и сейчас
Подписывайтесь на наш канал здесь и в телеграмм https://t.iss.one/meetups_evrone, чтобы быть в курсе будущих митапов и не пропускать полезные доклады!
Андрей Скиба / Uchi.ru
В компании Uchi.ru с ростом ее размера возникла необходимость в наблюдении за ключевыми…
Андрей Скиба / Uchi.ru
В компании Uchi.ru с ростом ее размера возникла необходимость в наблюдении за ключевыми…
🔥4
А я к вам с новостями.
FastAPI в версии
#fastapi #pydantic
FastAPI в версии
0.100.0-beta1
поддерживает Pydantic v2 в бета-режиме. Да-да, это тот самый Pydantic, внутренности которого написаны на Rust. Гайд по миграции можно почитать здесь, а релиз тут.#fastapi #pydantic
GitHub
Release 0.100.0-beta1 · fastapi/fastapi
Install with:
pip install --pre --upgrade fastapi pydantic
Features
✨ Beta support for Pydantic version 2 ✨
The internals of Pydantic v2 were rewritten in Rust and it's currently available in b...
pip install --pre --upgrade fastapi pydantic
Features
✨ Beta support for Pydantic version 2 ✨
The internals of Pydantic v2 were rewritten in Rust and it's currently available in b...
❤8🔥1
Зачем нужно делать кастомную базовую Pydantic модель?
Сейчас некоторые со мной не согласятся, но я часто рекомендую делать базовую
Наличие такой глобальной модели позволяет настраивать поведение всех моделей в приложении. Рассмотрю несколько кейсов, когда это может понадобится.
1) Контроль над входными данными.
Например, мы хотим округлять все поля которые называются
P.S.: В коментах подметили, что такой подход неявный, и я с этим согласен. Ничего не мешает для таких целей сделать ещё одну базовую модель (
2) Кастомый энкодер/декодер json.
Пакет
Это происходит из-за того, что операций по (дe)сериализации json в приложении может быть много, и смена библиотеки, в этом случае, дает ощутимый прирост к общей скорости.
В pydantic есть 2 опции в конфиге, которые позволяют изменять поведение энкодера и декодера. Выглядит это так:
Сейчас некоторые со мной не согласятся, но я часто рекомендую делать базовую
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):#pydantic
# orjson.dumps возвращает байты, поэтому нам надо их декодить, чтобы соответствовать сигнатуре json.dumps
return orjson.dumps(v, default=default).decode()
class CustomBaseModel(BaseModel):
class Config:
json_loads = orjson.loads
json_dumps = orjson_dumps
🔥10😱1
Коробка с питоном
Как раз сегодня искал фреимворк для организации работы консьюмера RabbitMQ и на глаза попался Propan - декларативный фреимворк для работы с очередями сообщений. Для чего это нужно? На базе очередей можно построить асинхронную коммуникацию сервисов, а это…
Автор Propan на Habr'е написал статью "Messaging для чайников. Утилизируем все возможности RabbitMQ на Python", где объясняет основы работы с этим брокером сообщений при помощи своего фреймворка.
Для начинающих - самое то.
#habr #propan #статья
Для начинающих - самое то.
#habr #propan #статья
🔥6
Как запускать синхронные функции в асинхронном роуте FastAPI?
Иногда так случается, что приходится использовать синхронный код в асинхронном роуте.
Если мы попытаемся вызвать синхронную функцию в асинхронном коде - наш event loop заблокируется и всё "зависнет" до тех пор, пока синхронный код не отработает.
Решений, как это сделать, на самом деле много. Самый простой вариант, который предоставляет FastAPI(а если быть точнее - Starlette, который использует anyio) - функция run_in_threadpool, которая запустит синхронный код в потоке:
А как бы вы решали/решаете такую проблему? Пишите в комментариях 😎 !
#fastapi #anyio
Иногда так случается, что приходится использовать синхронный код в асинхронном роуте.
Если мы попытаемся вызвать синхронную функцию в асинхронном коде - наш event loop заблокируется и всё "зависнет" до тех пор, пока синхронный код не отработает.
Решений, как это сделать, на самом деле много. Самый простой вариант, который предоставляет FastAPI
@app.get("/")Кстати, BackgroundTask использует тот же самый способ, только он не возвращает результат выполнения.
async def my_router():
result = await service.execute()
client = SyncClient()
return await run_in_threadpool(client.execute, data=result)
А как бы вы решали/решаете такую проблему? Пишите в комментариях 😎 !
#fastapi #anyio
❤5🤯1
Forwarded from Николай Хитров | Блог
Релиз
Себастьян закончил обновление
Чейнжлог совсем небольшой получился
https://fastapi.tiangolo.com/release-notes/#01000
p.s. в ближайшее время доберусь до чейнжлога pydantic v2 и сделаю обзорный пост
FastAPI
0.100.0🔥Себастьян закончил обновление
pydantic
-а. Теперь можно насладиться звуком ржавчины и приростом скорости при переходе на новую версию FastAPI
.Чейнжлог совсем небольшой получился
https://fastapi.tiangolo.com/release-notes/#01000
p.s. в ближайшее время доберусь до чейнжлога pydantic v2 и сделаю обзорный пост
🔥9❤1
Yoyo
В текущих реалиях практически любой сервис использующий реляционную БД не может обойтись без миграций. Так уж сложилось, что в нашем питонячьем мире, в проектах почти всегда можно увидеть ORM (например SQLAlchemy) и пакет, который позволяет управлять миграциями, работающий с конкретной ORM (в случае с Алхимией это alembic).
Но иногда попадаются такие проекты, в которых нам не нужна ORM, по разным причинам. В этом случае, для миграций можно использовать yoyo.
Yoyo - это простой мигратор схем для нашей БД. Миграции здесь записываются в виде скриптов на SQL или на Python.
Сгенерировать папку для миграций и конфиг можно вот так:
Внутри базы yoyo создает таблицу с логом всех операций (
Вот такая вот простая и удобная библиотека :)
Сайт | Sourcehut | PyPI
#библиотека
В текущих реалиях практически любой сервис использующий реляционную БД не может обойтись без миграций. Так уж сложилось, что в нашем питонячьем мире, в проектах почти всегда можно увидеть ORM (например SQLAlchemy) и пакет, который позволяет управлять миграциями, работающий с конкретной ORM (в случае с Алхимией это alembic).
Но иногда попадаются такие проекты, в которых нам не нужна ORM, по разным причинам. В этом случае, для миграций можно использовать yoyo.
Yoyo - это простой мигратор схем для нашей БД. Миграции здесь записываются в виде скриптов на SQL или на Python.
Сгенерировать папку для миграций и конфиг можно вот так:
yoyo init --database sqlite:///mydb.sqlite3 migrationsА теперь создадим миграцию:
yoyo newОпишем SQL для применения миграции (apply) и для её отката (rollback):
from yoyo import stepТеперь можно применить миграцию командой
__depends__ = {}
steps = [
step(
"CREATE TABLE TEST (a int);",
"DROP TABLE TEST"
)
]
yoyo apply
и после откатить её командой yoyo rollback
. Внутри базы yoyo создает таблицу с логом всех операций (
_yoyo_log
), таблицу с применёнными миграциями (_yoyo_migration
), а так же таблицу yoyo_lock
, которая позволяет заблокировать миграции, которые будут идти с нескольких инстансов приложений. Вот такая вот простая и удобная библиотека :)
Сайт | Sourcehut | PyPI
#библиотека
👏7🤯1
GIL скорее всего уберут из Python!
Руководящий совет объяснил статус PEP 703 (сделать GIL опциональным). Если кратко, то понятно следующее:
— Они намерены принять PEP 703, но всё ещё работают над деталями, предстоит много работы.
— Вероятно, лет через пять сборка без GIL будет ЕДИНСТВЕННОЙ сборкой, так как они не хотят разделять комьюнити на no-GIL и GIL.
— Совет не хочет повторения ситуации с Python 3, поэтому большое внимание будет уделено обратной совместимости.
— Прежде чем отказаться от GIL, они внимательно будут изучать работу комьюнити в этом направлении. Ребята хотят убедиться, что переход будет плавным, а поддержка режима no-GIL будет достаточна.
— Не смотря на все это, совет хочет иметь возможность "дать заднюю", если для комьюнити и языка это принесёт намного больше проблем, чем профита.
Новость просто невероятная. Остается надеяться на комьюнити, будет ли оно готово адаптировать свои библиотеки под этот режим?
#gil
Руководящий совет объяснил статус PEP 703 (сделать GIL опциональным). Если кратко, то понятно следующее:
— Они намерены принять PEP 703, но всё ещё работают над деталями, предстоит много работы.
— Вероятно, лет через пять сборка без GIL будет ЕДИНСТВЕННОЙ сборкой, так как они не хотят разделять комьюнити на no-GIL и GIL.
— Совет не хочет повторения ситуации с Python 3, поэтому большое внимание будет уделено обратной совместимости.
— Прежде чем отказаться от GIL, они внимательно будут изучать работу комьюнити в этом направлении. Ребята хотят убедиться, что переход будет плавным, а поддержка режима no-GIL будет достаточна.
— Не смотря на все это, совет хочет иметь возможность "дать заднюю", если для комьюнити и языка это принесёт намного больше проблем, чем профита.
Новость просто невероятная. Остается надеяться на комьюнити, будет ли оно готово адаптировать свои библиотеки под этот режим?
#gil
Discussions on Python.org
A Steering Council notice about PEP 703 (Making the Global Interpreter Lock Optional in CPython)
Posting for the whole Steering Council, on the subject of @colesbury’s PEP 703 (Making the Global Interpreter Lock Optional in CPython). Thank you, everyone, for responding to the poll on the no-GIL proposal. It’s clear that the overall sentiment is positive…
🔥8🤯6🎉2
Появился PEP 723, который предлагает "встраивать"
Предлагается добавить переменную
К примеру, вот так будет выглядеть скрипт, которому для работы нужна библиотека
#pep
pyproject.toml
в однофайловые скрипты. Предлагается добавить переменную
__pyproject__
, которая будет содержать в себе валидный TOML, описывающий метадату скрипта, в том числе как скрипт запускать и какие зависимости необходимы для запуска.К примеру, вот так будет выглядеть скрипт, которому для работы нужна библиотека
requests
и питон 3.11 или выше:__pyproject__ = """PEP прикольный, что-то такое есть в качестве экспериментального RFC в Rust. Из минусов хотел бы отметить то, что автоматическая установка зависимостей может привести к запуску нежелательного кода. Но решение банальное - перед тем как что-то запускать, проверяйте, что вы запускаете.
[project]
requires-python = ">=3.11"
dependencies = [
"requests<3",
]
"""
import requests
resp = requests.get("https://peps.python.org/api/peps.json")
print(resp.json())
#pep
Python Enhancement Proposals (PEPs)
PEP 723 – Inline script metadata | peps.python.org
This PEP specifies a metadata format that can be embedded in single-file Python scripts to assist launchers, IDEs and other external tools which may need to interact with such scripts.
🔥7👏1
Занимаюсь в рамках петпроекта обработкой текста, появилась потребность проверять на каком языке написан текст.
Сначала я попытался использовать langdetect, но он часто выдавал неправильные результаты. Как правило, плохие результаты выдавались по нескольким причинам:
1. Нет возможности ограничить языки, которые я хотел бы детектить. Мне надо определять всего четыре языка - украинский, русский, английский и немецкий.
2. Часто исследуемый мною текст слишком мал, из-за чего анализ ломался.
По итогу я пошел искать другую библиотеку и нашел lingua, которая успешно справляется с проблемами langdetect.
Важное отличие этой библиотеки от всех остальных в том, что она использует не только статистическую модель для определения языка, а ещё и механизмы, основанные на правилах - сначала определяется алфавит текста, ищутся символы которые уникальны для языка и после этого выбираются языки, на которых возможно написан текст.
Но есть возможность улучшить этот процесс. Можно самому ограничить языки, на которых возможно будет написан текст, а это как раз то, что мне и нужно:
Из-за ограничения языков вероятность совершить ошибку на небольших предложениях сокращается многократно. В добавок ко всему, ребята используют не только триграммы, которые очень часто используют для таких задач, а n-граммы от 1 до 5, из-за чего вероятность предсказания повышается.
Причина такого решения проста - чем короче входной текст, тем меньше n-грамм доступно, а если мы будем проверять триграммами короткие заголовки - будут случаться ошибки.
Ну и база - ограничение количества языков ускоряет работу и уменьшает потребление памяти, а при исследовании огромных текстов - это несомненный плюс.
#nlp #библиотека
Сначала я попытался использовать langdetect, но он часто выдавал неправильные результаты. Как правило, плохие результаты выдавались по нескольким причинам:
1. Нет возможности ограничить языки, которые я хотел бы детектить. Мне надо определять всего четыре языка - украинский, русский, английский и немецкий.
2. Часто исследуемый мною текст слишком мал, из-за чего анализ ломался.
По итогу я пошел искать другую библиотеку и нашел lingua, которая успешно справляется с проблемами langdetect.
Важное отличие этой библиотеки от всех остальных в том, что она использует не только статистическую модель для определения языка, а ещё и механизмы, основанные на правилах - сначала определяется алфавит текста, ищутся символы которые уникальны для языка и после этого выбираются языки, на которых возможно написан текст.
Но есть возможность улучшить этот процесс. Можно самому ограничить языки, на которых возможно будет написан текст, а это как раз то, что мне и нужно:
from lingua import Language, LanguageDetectorBuilder
languages = [Language.ENGLISH, Language.RUSSIAN, Language.GERMAN, Language.UKRAINIAN]
detector = LanguageDetectorBuilder.from_languages(*languages).build()
print(detector.detect_language_of("Hello from box with python!")) # Language.ENGLISH
print(detector.detect_language_of("Привет от коробки с питоном!")) # Language.RUSSIAN
Из-за ограничения языков вероятность совершить ошибку на небольших предложениях сокращается многократно. В добавок ко всему, ребята используют не только триграммы, которые очень часто используют для таких задач, а n-граммы от 1 до 5, из-за чего вероятность предсказания повышается.
Причина такого решения проста - чем короче входной текст, тем меньше n-грамм доступно, а если мы будем проверять триграммами короткие заголовки - будут случаться ошибки.
Ну и база - ограничение количества языков ускоряет работу и уменьшает потребление памяти, а при исследовании огромных текстов - это несомненный плюс.
#nlp #библиотека
PyPI
langdetect
Language detection library ported from Google's language-detection.
🔥11❤2🤩1
Немного девопсовский пост, так как на предыдущем месте работы я много админил линукса.
Автоматизация - один из столпов работы любого админа, так как подготавливать сервера руками - занятие тяжелое и трудозатратное.
Для этого я всегда выбирал Ansible - это довольно простой инструмент, который позволяет настраивать сервера из специальных yaml конфигов, которые называются плейбуками.
Но какой бы вы инструмент не выбрали, рано или поздно конфигурация будет усложняться, а плейбуков/скриптов станет много. В какой-то момент всё это может сломаться, поэтому любую автоматизацию надо тестировать.
Когда я админил, команда не хотела полностью завязываться на Ansible (соответственно Molecule отпадает), решено было искать инструмент, который позволял бы тестировать состояние сервера после работы любой автоматизации.
И я нашел такой инструмент, имя ему - testinfra. Это плагин для pytest, который позволяет лаконично описывать тесты проверяющие состояние сервера.
Например, мы написали автоматизацию, которая устанавливает nginx. Проверим, что он установлен:
Напоследок, вот вам еще кейс использования: одно время при помощи testinfra я тестировал правильность сборки контейнеров - все ли есть права, запустился ли сервис, в порядке ли конфиги и так далее.
#devops #библиотека
Автоматизация - один из столпов работы любого админа, так как подготавливать сервера руками - занятие тяжелое и трудозатратное.
Для этого я всегда выбирал Ansible - это довольно простой инструмент, который позволяет настраивать сервера из специальных yaml конфигов, которые называются плейбуками.
Но какой бы вы инструмент не выбрали, рано или поздно конфигурация будет усложняться, а плейбуков/скриптов станет много. В какой-то момент всё это может сломаться, поэтому любую автоматизацию надо тестировать.
Когда я админил, команда не хотела полностью завязываться на Ansible (соответственно Molecule отпадает), решено было искать инструмент, который позволял бы тестировать состояние сервера после работы любой автоматизации.
И я нашел такой инструмент, имя ему - testinfra. Это плагин для pytest, который позволяет лаконично описывать тесты проверяющие состояние сервера.
Например, мы написали автоматизацию, которая устанавливает nginx. Проверим, что он установлен:
def test_nginx_is_installed(host):А теперь проверим, что сервис с ним запущен:
nginx = host.package("nginx")
assert nginx.is_installed
def test_nginx_running_and_enabled(host):Самое важное - для него существует много connection backend'ов, которые позволяют подключаться к серверам для теста как по SSH (через paramiko), так и используя инвентарь Ansible. Так же есть бекенды для docker/podman/salt/kubectl/openshift/winrm/lxc - обо всём этом можно почитать здесь.
nginx = host.service("nginx")
assert nginx.is_running
assert nginx.is_enabled
Напоследок, вот вам еще кейс использования: одно время при помощи testinfra я тестировал правильность сборки контейнеров - все ли есть права, запустился ли сервис, в порядке ли конфиги и так далее.
#devops #библиотека
🔥12❤1🤯1
Тианголо (создатель FastAPI) предложил новый PEP 727, который позволяет стандартизировать механизм документирования параметров.
Причина проста - существует много псевдо-стандартов по форматированию параметров в docstring (например свои стандарты есть у numpy, гугла, много их!), но не все редакторы/IDE имеют возможность поддерживать эти "микроязыки". Он предлагает стандартизировать подход, используя существующий мощный инструмент в виде аннотаций типов.
Основное предложение - добавление в
А вот как это будет выглядеть:
Выглядит интересно, но важно понимать - автор пытается создать ещё один стандарт. Поддержит ли его комьюнити и уйдет ли PEP в работу? Остается только гадать.
#pep
Причина проста - существует много псевдо-стандартов по форматированию параметров в docstring (например свои стандарты есть у numpy, гугла, много их!), но не все редакторы/IDE имеют возможность поддерживать эти "микроязыки". Он предлагает стандартизировать подход, используя существующий мощный инструмент в виде аннотаций типов.
Основное предложение - добавление в
typing
новой функции doc
, которая принимает единственный параметр documentation
. Ожидается, что эта функция будет использоваться вместе с Annotated
.А вот как это будет выглядеть:
def create_user(Тианголо заранее позаботился и о старых версиях - он не стал выдумывать новый синтаксис, так же предлагается добавить
lastname: Annotated[str, doc("The **last name** of the newly created user")],
firstname: Annotated[str | None, doc("The user's **first name**")] = None,
) -> Annotated[User, doc("The created user after saving in the database")]:
"""
Create a new user in the system, it needs the database connection to be already
initialized.
"""
pass
doc()
в пакет typing_extensions
, который используют старые версии питона для исключения проблем с совместимостью. Выглядит интересно, но важно понимать - автор пытается создать ещё один стандарт. Поддержит ли его комьюнити и уйдет ли PEP в работу? Остается только гадать.
#pep
Python Enhancement Proposals (PEPs)
PEP 727 – Documentation in Annotated Metadata | peps.python.org
This PEP proposes a standardized way to provide documentation strings for Python symbols defined with Annotated using a new class typing.Doc.
❤9👏1🤔1🤯1
Недавно мой знакомый @nesclass (можете ему писать по теме доклада) выступал c докладом "Асинхронное варение MongoDB в Python" на Pytup.
Автор объяснил наглядно в чем различие реляционных баз от документно-ориентированных, немного рассказал про подходы работы с БД, затронул тему object mapper'ов и много рассказал про Beanie - ODM для работы с MongoDB (про которую я писал) и саму монгу.
Доклад отлично подойдет для тех, кто хочет ознакомиться с этим инструментом и послушать про подводные камни, с которыми часто встречаются новички.
#посмотреть
Автор объяснил наглядно в чем различие реляционных баз от документно-ориентированных, немного рассказал про подходы работы с БД, затронул тему object mapper'ов и много рассказал про Beanie - ODM для работы с MongoDB (про которую я писал) и саму монгу.
Доклад отлично подойдет для тех, кто хочет ознакомиться с этим инструментом и послушать про подводные камни, с которыми часто встречаются новички.
#посмотреть
YouTube
Асинхронное варение MongoDB в Python - Даниил Неслуховский, старший разработчик, Элитриум
🔥8🤩2
Если вам приходилось работать с bash, например парсить логи, вы наверняка видели или использовали команды следующего вида:
Символ
В Elixir есть оператор конвейера
Согласитесь, так удобнее работать с коллекциями, особенно там где данных много и их хочется как-то отфильтровать. В случае использования конвейеров нам больше не надо строить громоздкие циклы, а код прост и понятен.
Если вам интересно. как можно сделать такое в Python, то для вас есть библиотека Pipe. Реализация очень простая - библиотека добавляет класс Pipe который переопределяет оператор
Например, вот так мы можем получить сумму товаров, цена которых больше тысячи:
cat app.log | grep 'exception' | awk '{ print $2 }'
Здесь мы последовательно считываем содержимое файла app.log
, фильтруем по подстроке exception
и выводим вторую колонку. Символ
|
, которая разделяет команды называется "пайпом" - он перенаправляет вывод из одной команды в другую, а вся эта конструкция в целом называется конвейером, и она очень часто используется в функциональном программировании.В Elixir есть оператор конвейера
|>
который позволяет передавать результат выполнения левого выражения в правое. Это позволяет делать вот такие штуки:1..10Здесь мы генерируем список от 1 до 10, умножаем каждый элемент на 2 и фильтруем только те, которые больше 10.
|> Enum.map(fn x -> x * 2 end)
|> Enum.filter(fn x -> x > 10 end)
[12, 14, 16, 18, 20]
Согласитесь, так удобнее работать с коллекциями, особенно там где данных много и их хочется как-то отфильтровать. В случае использования конвейеров нам больше не надо строить громоздкие циклы, а код прост и понятен.
Если вам интересно. как можно сделать такое в 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
#библиотекаGitHub
GitHub - JulienPalard/Pipe: A Python library to use infix notation in Python
A Python library to use infix notation in Python. Contribute to JulienPalard/Pipe development by creating an account on GitHub.
🔥8❤2👏1🤔1😱1
Коробка с питоном
Как раз сегодня искал фреимворк для организации работы консьюмера RabbitMQ и на глаза попался Propan - декларативный фреимворк для работы с очередями сообщений. Для чего это нужно? На базе очередей можно построить асинхронную коммуникацию сервисов, а это…
Помните, я рассказывал про такой фреимворк как Propan? В общем, программа Propan удаляется на смену Propan пришел FastStream, и весь новый функционал будет попадать в него.
Первой моей реакцией было "што" и "зачем", ведь на первый взгляд может показаться, что поменялись только орга и название. Давайте разбираться.
Во-первых, за фреимворком стоит не только сам Lancetnik, а целая команда из AirtAI, что является очень сильным усилением со стороны как разработки, так и поддержки.
Второе, FastKafka переходит в такой же статус как и Propan. Всё по той же причине - новый функционал будут добавлять в FastStream.
В свою очередь FastStream - это фреимворк, базированный на идеях FastKafka и Propan, который хочет взять от них самое лучшее и создать единый способ для написания сервисов, работающих с очередями.
Третье, что показалось мне важным, разработчик Propan признаётся, что сделать унифицированный RPC для всех брокеров (например для Kafka) - задача сложная, особенно когда брокер by design плохо рассчитан на такую функциональность. Всё сводилось к тому, что тот самый простой высокоуровневый интерфейс плохо скрывал недостатки реализации, поэтому в FastStream от него отказались.
Ещё генерацию темплейтов удалили, теперь проект можно генерировать при помощи cookiecutter.
А что нового уже принёс FastStream?
В первую очередь, мне понравился механизм фильтров. Ещё добавили кастомную сериализацию - по умолчанию FastStream работает с Json, но если у вас Protobuf, Avro или msgpack - больше никаких проблем нет, можно добавить собственную логику для сериализации.
Отдельно хотел бы выделить систему мидлварей - теперь трассировку, логи, обогащение сообщений метаинформацией делать намного проще.
Очень надеюсь, что проект будет развиваться семимильными шагами, ведь идеи FastKafka и Propan мне очень сильно понравились, а сам Propan я очень часто рекомендовал знакомым.
P.S. Оказывается кастомная сериализация уже была.
#библиотека
Первой моей реакцией было "што" и "зачем", ведь на первый взгляд может показаться, что поменялись только орга и название. Давайте разбираться.
Во-первых, за фреимворком стоит не только сам Lancetnik, а целая команда из AirtAI, что является очень сильным усилением со стороны как разработки, так и поддержки.
Второе, FastKafka переходит в такой же статус как и Propan. Всё по той же причине - новый функционал будут добавлять в FastStream.
В свою очередь FastStream - это фреимворк, базированный на идеях FastKafka и Propan, который хочет взять от них самое лучшее и создать единый способ для написания сервисов, работающих с очередями.
Третье, что показалось мне важным, разработчик Propan признаётся, что сделать унифицированный RPC для всех брокеров (например для Kafka) - задача сложная, особенно когда брокер by design плохо рассчитан на такую функциональность. Всё сводилось к тому, что тот самый простой высокоуровневый интерфейс плохо скрывал недостатки реализации, поэтому в FastStream от него отказались.
Ещё генерацию темплейтов удалили, теперь проект можно генерировать при помощи cookiecutter.
А что нового уже принёс FastStream?
В первую очередь, мне понравился механизм фильтров. Ещё добавили кастомную сериализацию - по умолчанию FastStream работает с Json, но если у вас Protobuf, Avro или msgpack - больше никаких проблем нет, можно добавить собственную логику для сериализации.
Отдельно хотел бы выделить систему мидлварей - теперь трассировку, логи, обогащение сообщений метаинформацией делать намного проще.
Очень надеюсь, что проект будет развиваться семимильными шагами, ведь идеи FastKafka и Propan мне очень сильно понравились, а сам Propan я очень часто рекомендовал знакомым.
P.S. Оказывается кастомная сериализация уже была.
#библиотека
GitHub
GitHub - ag2ai/faststream: FastStream is a powerful and easy-to-use Python framework for building asynchronous services interacting…
FastStream is a powerful and easy-to-use Python framework for building asynchronous services interacting with event streams such as Apache Kafka, RabbitMQ, NATS and Redis. - ag2ai/faststream
🔥7🤔2🤯1
На второе октября намечен релиз Python 3.12, поэтому Никита Соболев (opensource разработчик и контрибьютор в сpython) рассказывает про новинки в новой версии и чуть затрагивает то, что ожидает нас в 3.13.
Рекомендую посмотреть, чтобы оставаться в теме новых обновлений.
#посмотреть
Рекомендую посмотреть, чтобы оставаться в теме новых обновлений.
#посмотреть
YouTube
«Новинки в Python 3.12 и даже немного про 3.13», Никита Соболев
«Окей, Никита, что нового в Python?»
Еще одни спикер #GPDays2023 Никита Соболев – Open Source разработчик и любитель Python рассказал о чистке stdlib, PEP 695, новом синтаксисе для типизации, а также uops из Python 3.13:
01:19 Что нового в новом Python…
Еще одни спикер #GPDays2023 Никита Соболев – Open Source разработчик и любитель Python рассказал о чистке stdlib, PEP 695, новом синтаксисе для типизации, а также uops из Python 3.13:
01:19 Что нового в новом Python…
🔥5
Недавно пришлось писать конвертор который транслировал Markdown в довольно специфичный формат.
Была следующая идея - мне нужен парсер, который перегонит Markdown в синтаксическое дерево, которое я буду обходить.
С обычным python-markdown в этом плане банально неудобно работать - у него нет простого и расширяемого API (как минимум), который бы позволял решить мою задачу.
А вот у mistletoe такое API есть. Например, вот так выглядит рендерер markdown в jira:
#библиотека
Была следующая идея - мне нужен парсер, который перегонит Markdown в синтаксическое дерево, которое я буду обходить.
С обычным python-markdown в этом плане банально неудобно работать - у него нет простого и расширяемого API (как минимум), который бы позволял решить мою задачу.
А вот у mistletoe такое API есть. Например, вот так выглядит рендерер markdown в jira:
class JiraRenderer(BaseRenderer):Ещё mistletoe можно использовать как утилиту. Например, вот так markdown-файл можно перевести в тот же формат Jira:
def render_strong(self, token):
template = '*{}*'
return template.format(self.render_inner(token))
def render_emphasis(self, token):
template = '_{}_'
return template.format(self.render_inner(token))
mistletoe foo.md --renderer mistletoe.contrib.jira_renderer.JiraRendererПоэтому, если вам нужна небольшая, но расширяемая библиотека для работы с markdown - берите её, не прогадаете.
#библиотека
🔥17👏1