Я всё чаще и чаще замечаю 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 и выше на Unix-платформах и 3.8 и выше на Windows.
Очень надеюсь что с этого что-то вырастет.
#библиотека
Совершенно недавно я нашел вот такой HTTP сервер на Rust для приложений на Python - Granian.
Разработчики ставят перед собой следующие цели:
+ Поддержка HTTP версий 1, 2 и 3
+ Один пакет для всех платформ
+ Сервер должен заменить Gunicorn/Uvicorn
+ Обеспечение большей производительности по сравнению с конкурентами.
Сейчас оно умеет в:
+ ASGI/3 и RSGI
+ HTTP/1 и HTTP/2
+ Вебсокеты над HTTP/1 и HTTP/2
+ Поддержка SSL
К сожалению проект пока что в состоянии разработки, поддерживает Питон 3.7 и выше на Unix-платформах и 3.8 и выше на Windows.
Очень надеюсь что с этого что-то вырастет.
#библиотека
GitHub
GitHub - emmett-framework/granian: A Rust HTTP server for Python applications
A Rust HTTP server for Python applications. Contribute to emmett-framework/granian development by creating an account on GitHub.
Коробка с питоном
Я всё чаще и чаще замечаю Rust рядом с Python... Совершенно недавно я нашел вот такой HTTP сервер на Rust для приложений на Python - Granian. Разработчики ставят перед собой следующие цели: + Поддержка HTTP версий 1, 2 и 3 + Один пакет для всех платформ…
К слову, эти же чуваки сделали довольно известный в узких кругах фреимворк emmett.
Это фреимворк с кучей полезностей и различными новыми подходами. Вот самое интересное:
1) ORM на pyDAl, которая умеет даже в Монгу и FireBird писать! Ну и миграции, каллбеки (похожи на сигналы в Django) и ещё огромная куча всего, почитайте.
2) Валидаторы, правда не такие красивые как c Pydantic.
3) Система авторизации с гибкой системой групп.
4) Даже различные бекенды для кеша есть!
5) Очень интересная система пайплайнов, чем-то похожая на middleware, но с возможностью делать различные действия в зависимости от состояния пайпа.
6) Не менее интересная система сервисов, которая позволяет отдавать ответ не только в html, а в каком-то json или xml.
7) Система расширений.
8) Ну и CLI.
9) А для тех кому нужен REST есть расширение.
Уверен, что почти каждый читающий не знал о существовании этого фреймворка, а жаль. К счастью или сожалению сейчас господствуют микрофреимворки испытывающие unix-way - делай что-то одно и делай это хорошо.
#библиотека
Это фреимворк с кучей полезностей и различными новыми подходами. Вот самое интересное:
1) ORM на pyDAl, которая умеет даже в Монгу и FireBird писать! Ну и миграции, каллбеки (похожи на сигналы в Django) и ещё огромная куча всего, почитайте.
2) Валидаторы, правда не такие красивые как c Pydantic.
3) Система авторизации с гибкой системой групп.
4) Даже различные бекенды для кеша есть!
5) Очень интересная система пайплайнов, чем-то похожая на middleware, но с возможностью делать различные действия в зависимости от состояния пайпа.
6) Не менее интересная система сервисов, которая позволяет отдавать ответ не только в html, а в каком-то json или xml.
7) Система расширений.
8) Ну и CLI.
9) А для тех кому нужен REST есть расширение.
Уверен, что почти каждый читающий не знал о существовании этого фреймворка, а жаль. К счастью или сожалению сейчас господствуют микрофреимворки испытывающие unix-way - делай что-то одно и делай это хорошо.
#библиотека
GitHub
GitHub - emmett-framework/emmett: The web framework for inventors
The web framework for inventors. Contribute to emmett-framework/emmett development by creating an account on GitHub.
Уже какую неделю подряд на Reddit (да и в англоязычных Python комьюнити) хайпит Flet.
Flet - это фреимворк который позволяет строить интерактивные десктопные/мобильные/веб приложения на различных ЯП (пока что увидел только поддержку Python), в итоге получаем SPA/PWA. Построено это всё на Flutter. Пример кода на скриншоте.
Подход с декларативным построением интерфейса вообще не новый - взгляните на Swift UI или же Jetpack Compose. Вопрос лишь в том, кто это использует?
Мне кажется, что:
1. Скорее всего подойдет для тех, кому нужно быстро накостылять MVP или взять замену tkinter.
2. Кейса, где это потащат в прод я не могу придумать по одной простой причине - множество гвоздей забивать микроскопом неудобно. Лучше взять молоток в виде React и спокойно с ним работать.
Во всяком случае - выглядит прикольно. Есть документация с примерами.
#библиотека
Flet - это фреимворк который позволяет строить интерактивные десктопные/мобильные/веб приложения на различных ЯП (пока что увидел только поддержку Python), в итоге получаем SPA/PWA. Построено это всё на Flutter. Пример кода на скриншоте.
Подход с декларативным построением интерфейса вообще не новый - взгляните на Swift UI или же Jetpack Compose. Вопрос лишь в том, кто это использует?
Мне кажется, что:
1. Скорее всего подойдет для тех, кому нужно быстро накостылять MVP или взять замену tkinter.
2. Кейса, где это потащат в прод я не могу придумать по одной простой причине - множество гвоздей забивать микроскопом неудобно. Лучше взять молоток в виде React и спокойно с ним работать.
Во всяком случае - выглядит прикольно. Есть документация с примерами.
#библиотека
Продолжаем смотреть на питоновские библиотеки! На этот раз снова не обойдется без влияния Rust - сегодня мы будем рассматривать библиотеки которые реализуют типы Result и Option.
В стандартной библиотеке Rust есть такой тип как Option - он позволяет, в случае если что-то пошло не так вернуть None, иначе вернуть само значение. Ещё есть Result, который позволяет вернуть либо значение, либо ошибку, которую далее уже должна обработать вызывающая функция.
Всё это нужно по причине того, что в Rust нет конструкции
Зачем это нужно в Python?А оно там не нужно Есть несколько причин:
1) Вы пишите на Rust
3) Такой подход вам ближе
2) Вы пишите в парадигме функционального программирования.
В остальном, как по мне, это просто не нужно. Множить подходы (особенно к обработке ошибок) - самое неприятное что можно сделать в языке.
Но мы продолжаем. Для реализации этих типов есть несколько питоновских библиотек. Вот они: safetywrap и option. Safetywrap мне показался более полным, поэтому будем рассматривать его.
Задача - написать функцию, которая будет проверять значение на отрицательность. Если оно отрицательное - выводим ошибку. С safetywrap это будет выглядеть следующим образом:
#библиотека
В стандартной библиотеке Rust есть такой тип как Option - он позволяет, в случае если что-то пошло не так вернуть None, иначе вернуть само значение. Ещё есть Result, который позволяет вернуть либо значение, либо ошибку, которую далее уже должна обработать вызывающая функция.
Всё это нужно по причине того, что в Rust нет конструкции
try... except
и господствует ФП, которое позволяет строить мощные функциональные конвейеры для обработки получаемых внутри программы данных.Зачем это нужно в Python?
1) Вы пишите на Rust
3) Такой подход вам ближе
2) Вы пишите в парадигме функционального программирования.
В остальном, как по мне, это просто не нужно. Множить подходы (особенно к обработке ошибок) - самое неприятное что можно сделать в языке.
Но мы продолжаем. Для реализации этих типов есть несколько питоновских библиотек. Вот они: safetywrap и option. Safetywrap мне показался более полным, поэтому будем рассматривать его.
Задача - написать функцию, которая будет проверять значение на отрицательность. Если оно отрицательное - выводим ошибку. С safetywrap это будет выглядеть следующим образом:
def check_value_not_negative(val: int) -> Result[int, str]:Как использовать эту функцию? Можно просто её вызвать и в зависимости от результата мы получим либо тип Ok, либо тип Err.
if val >= 0:
return Ok(val)
return Err(f"{val} is negative!")
print(check_value_not_negative(1)) # Ok(1)Но самый сок - это то, что Result содержит в себе кучу полезных функций. Например, в случае получения ошибки мы можем вернуть None или любое другое значение:
print(check_value_not_negative(-1)) # Err('-1 is negative!')
print(check_value_not_negative(-1).or_(None)) # NoneИли проверить, равно ли значение единице, и если нет - вывести сообщение об этом:
print(check_value_not_negative(2).and_then(Как видно, эти типы позволяют писать код, который будет эффективно обрабатывать ошибки, не прибегая к куче
lambda result: Result.ok_if(lambda x: x == 1, result).map_err(
lambda _: "Не равно единице"
)
)) # Err('Не равно единице')
if
и try...except...
Мне нравится такой подход, а вам?#библиотека
FastAPI обновился до 0.89.0 и сделал фичу которой давно не хватало - наконец возвращаемый тип можно писать в аннотациях. Раньше, чтобы OpenAPI дока по нему сгенерировалась, надо было делать так:
Кому интересны детали - вот PR.
#fastapi
@app.get("/", response_model=Model)Теперь же можем делать вот так:
def endpoint():
return Model(name="Yurii")
@app.get("/")Мне до сих пор не понятно, почему так не сделали раньше. Возможно автору такой метод виделся удобным.
def endpoint() -> Model:
return Model(name="Yurii")
Кому интересны детали - вот PR.
#fastapi
GitHub
✨ Add support for function return type annotations to declare the `response_model` by uriyyo · Pull Request #1436 · tiangolo/fastapi
I love the idea of OpenAPI auto-generated schema and the FastAPI at all 😄
This is a feature request.
When I was working with FastAPI I thought that it will be a great idea to use function return ty...
This is a feature request.
When I was working with FastAPI I thought that it will be a great idea to use function return ty...
Разговоры шли давно, но 9ого числа представили PEP 703, который предлагает сделать GIL опциональным. Прототип опубликован в репозитории nogil.
В качестве основания используется то, что Python используют для ML, а GIL - это серьезное препятствие для параллельных вычислений.
В этом PEP так же привели работу с PEP 684, который предлагает прекратить использовать GIL между несколькими интерпретаторами в процессе.
Как думаете, могут ли действительно убрать/сделать опциональным GIL?
#pep
В качестве основания используется то, что Python используют для ML, а GIL - это серьезное препятствие для параллельных вычислений.
В этом PEP так же привели работу с PEP 684, который предлагает прекратить использовать GIL между несколькими интерпретаторами в процессе.
Как думаете, могут ли действительно убрать/сделать опциональным GIL?
#pep
Python Enhancement Proposals (PEPs)
PEP 703 – Making the Global Interpreter Lock Optional in CPython | peps.python.org
CPython’s global interpreter lock (“GIL”) prevents multiple threads from executing Python code at the same time. The GIL is an obstacle to using multi-core CPUs from Python efficiently. This PEP proposes adding a build configuration (--disable-gil) to...
Forwarded from Питонические атаки
В 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.
Дело в том, что f-строки в язык занесли в версии 3.6, когда балом правил еще старый LL(1) парсер, который было сложно расширять, поэтому для f-строк был написан отдельный маленький парсер. Из-за этого они получились слегка неполноценными, а еще в этом отдельном парсере, само собой, были отдельные новые баги. Самое яркое ограничение — это то, что внутри f-строк нельзя использовать те же кавычки, в которых лежит сама строка. Это ж капец как неудобно, что приходится другие кавычки использовать, чтобы просто достать что-то из словаря. У меня линтер на это ругается, и приходится ему каждый раз объяснять, что тут красиво никак не сделать.
Вот, в 3.12 разбор f-строк доверят основному PEG-парсеру, а сам синтаксис f-строк станет частью грамматики языка. Можно будет использовать любые кавычки, которые нравятся. А еще бесконечно вложенные f-строки. Не знаю, зачем нам это, но хорошо, что станет можно. Жду 3.12.
Python Enhancement Proposals (PEPs)
PEP 701 – Syntactic formalization of f-strings | peps.python.org
This document proposes to lift some of the restrictions originally formulated in PEP 498 and to provide a formalized grammar for f-strings that can be integrated into the parser directly. The proposed syntactic formalization of f-strings will have some ...
Когда-то давно, когда я только изучал Django, мне хотелось избавиться от бойлерплейта в темплейтах и вынести некоторые части шаблонов (например кнопки) в какие-то отдельные сущности которые можно переиспользовать - например в виде компонентов.
К счастью, в Django есть решение для этого и оно называется template tags. Но у него есть несколько проблем:
1) Необходимо пробрасывать руками js и css зависимости для конкретного тега там, где он используется.
2) Теги плохо кастомизируются, например нет возможности изменить поведение тега, обязательно нужно его переписывать.
Решением этих вопросов занимается пакет с названием django-components. Он предоставляет возможность делать простые, но в то же время мощные переиспользуемые компоненты. А как он справляется с проблемами выше?
1) При объявлении компонента будут грузиться только те js и css, которые указаны в классе компонента. Класс компонента выглядит как-то так:
2) Для изменения поведения компонента можно использовать слоты - это что-то вроде django-блоков внутри компонента. Например, мы можем сделать блок
#django #библиотека
К счастью, в Django есть решение для этого и оно называется template tags. Но у него есть несколько проблем:
1) Необходимо пробрасывать руками js и css зависимости для конкретного тега там, где он используется.
2) Теги плохо кастомизируются, например нет возможности изменить поведение тега, обязательно нужно его переписывать.
Решением этих вопросов занимается пакет с названием django-components. Он предоставляет возможность делать простые, но в то же время мощные переиспользуемые компоненты. А как он справляется с проблемами выше?
1) При объявлении компонента будут грузиться только те js и css, которые указаны в классе компонента. Класс компонента выглядит как-то так:
from django_components import componentСам js/css рендерится только там, где указаны теги
@component.register("calendar")
class Calendar(component.Component):
template_name = "calendar/calendar.html"
def get_context_data(self, date):
return {
"date": date,
}
class Media:
css = "calendar/calendar.css"
js = "calendar/calendar.js"
component_js_dependencies
и component_css_dependencies
.2) Для изменения поведения компонента можно использовать слоты - это что-то вроде django-блоков внутри компонента. Например, мы можем сделать блок
body
внутри компонента и изменять его вид тогда, когда нам нужно:<div class="calendar-component">А теперь импортируем компонент и меняем его body:
<div class="header">
{% slot "header" %}Заголовок календаря{% endslot %}
</div>
<div class="body">
{% slot "body" %}Сегодня <span>{{ date }}</span>{% endslot %}
</div>
</div>
{% component_block "calendar" date="2020-06-06" %}Github | PyPi
{% slot "body" %}А сегодня точно <span>{{ date }}</span>?{% endslot %}
{% endcomponent_block %}
#django #библиотека
Если вы хоть раз задумывались о том, можно ли фичи FastAPI (автогенерация OpenAPI, интеграция с Pydantic, поддержка асинхронности и т.д.) добавить в Django, то я пришел вас обрадовать - есть такой проект под названием django-ninja.
Из приятных фич, которые можно встретить здесь:
1) Версионирование и возможность создания нескольких API инстансов со своей авторизацией и т.д.
2) Класс схемы интегрирован с модельками Django, поэтому можно писать что-то вроде такого:
4) Пагинация! При чем в документации показано, как можно сделать собственный кастомный класс для неё.
5) Поддержка кастомных рендереров ответов, что позволяет перевести сериализацию на ORJSON или отдавать ответы в XML, например.
6) Работа с аутентификацией из под коробки.
7) Ну и асинхронность, тем более разработчики Django работают над ней.
А в остальном он очень похож на FastAPI, особенно когда речь идет о работе с аргументами, схемами и OpenAPI.
Как по мне, выглядит как достойная замена DRF, при чем довольно простая. И об этом я говорю не просто так - в последнее время я делал проекты на FastAPI и возвращаться на Django и тем более DRF было очень непривычно.
Github | Документация
#django #библиотека
Из приятных фич, которые можно встретить здесь:
1) Версионирование и возможность создания нескольких API инстансов со своей авторизацией и т.д.
2) Класс схемы интегрирован с модельками Django, поэтому можно писать что-то вроде такого:
@api.get("/tasks", response=List[TaskSchema])3) Можно делать схемы из моделей, прям как в DRF.
def tasks(request):
return Task.objects.all()
4) Пагинация! При чем в документации показано, как можно сделать собственный кастомный класс для неё.
5) Поддержка кастомных рендереров ответов, что позволяет перевести сериализацию на ORJSON или отдавать ответы в XML, например.
6) Работа с аутентификацией из под коробки.
7) Ну и асинхронность, тем более разработчики Django работают над ней.
А в остальном он очень похож на FastAPI, особенно когда речь идет о работе с аргументами, схемами и OpenAPI.
Как по мне, выглядит как достойная замена DRF, при чем довольно простая. И об этом я говорю не просто так - в последнее время я делал проекты на FastAPI и возвращаться на Django и тем более DRF было очень непривычно.
Github | Документация
#django #библиотека
django-ninja.dev
Django Ninja
Django Ninja - Django REST framework with high performance, easy to learn, fast to code.
Немного про роутинг в FastAPI
Если вы пользовались FastAPI, то наверняка знаете, что роут можно сделать либо асинхронным, либо синхронным. Так когда какой надо делать?
Скорее всего первая мысль которая придет вам в голову будет звучать как-то так - если у нас есть I/O-bound задачи (например работа с БД), то надо использовать асинхронщину, если всё остальное - потоки, процессы и так далее. Но тут есть несколько нюансов:
1) Под капотом FastAPI отлично справляется с обработкой как синхронных, так и асинхронных роутов. Если роут асинхронный, то задача по его обработке запустится в
2) Так как синхронные роуты запускаются в
Возьмем вот такой роут:
А теперь возьмем вот такой роут:
Поэтому, если вам нужно написать на FastAPI небольшой CRUD и вы думаете тащить асинхронную ORM - задумайтесь, а надо ли она вам там вообще?
Ссылки:
- Path operation functions
#fastapi
Если вы пользовались FastAPI, то наверняка знаете, что роут можно сделать либо асинхронным, либо синхронным. Так когда какой надо делать?
Скорее всего первая мысль которая придет вам в голову будет звучать как-то так - если у нас есть I/O-bound задачи (например работа с БД), то надо использовать асинхронщину, если всё остальное - потоки, процессы и так далее. Но тут есть несколько нюансов:
1) Под капотом FastAPI отлично справляется с обработкой как синхронных, так и асинхронных роутов. Если роут асинхронный, то задача по его обработке запустится в
event loop
, если синхронный - то в thread pool
.2) Так как синхронные роуты запускаются в
thread pool
, иногда просто нет вообще никакого смысла тащить в проект асинхронную ORM, так как всё и так будет работать не блокируя основное приложение.Возьмем вот такой роут:
@router.get("/nonblocking-sync-operation")После того как мы перейдем по этому роуту, мы будем ждать 10 секунд и в конце получим ответ. При этом сам FastAPI не заблокируется, и сможет обрабатывать другие подключения - потому что функция запустилась в отдельном потоке.
def nonblocking_sync_operation():
time.sleep(10)
return {"test": "test"}
А теперь возьмем вот такой роут:
@router.get("/blocking-sync-operation")Здесь после перехода по роуту функция запустится в event loop и sleep заблокирует всё приложение до тех пор, пока он не пройдет. То есть, FastAPI вообще перестанет принимать подключения до тех пор, пока функция не выполнится.
async def blocking_sync_operation():
time.sleep(10)
return {"test": "test"}
Поэтому, если вам нужно написать на FastAPI небольшой CRUD и вы думаете тащить асинхронную ORM - задумайтесь, а надо ли она вам там вообще?
Ссылки:
- Path operation functions
#fastapi
В PEP 695 предлагают наконец переделать синтаксис для указания дженериков и ввести новый оператор для указания алиасов.
1) Что там с дженериками?
Например, если раньше было так:
Раньше алиасы типов записывались вот так:
#pep
1) Что там с дженериками?
Например, если раньше было так:
_T_co = TypeVar("_T_co", covariant=True, bound=str)То сейчас предлагают сделать так:
class ClassA(Generic[_T_co]):
def method1(self) -> _T_co:
...
class ClassA[T: str]:2) А что с алиасами?
def method1(self) -> T:
...
Раньше алиасы типов записывались вот так:
_T = TypeVar("_T")Сейчас предлагают сделать вот так:
ListOrSet: TypeAlias = list[_T] | set[_T]
type ListOrSet[T] = list[T] | set[T]Если не ошибаюсь, то ждем в 3.12, PEP уже приняли.
#pep
Python Enhancement Proposals (PEPs)
PEP 695 – Type Parameter Syntax | peps.python.org
This PEP specifies an improved syntax for specifying type parameters within a generic class, function, or type alias. It also introduces a new statement for declaring type aliases.
Очень годный доклад о том как начинать проекты на Django.
Рассмотрели нужность батареек, как правильно писать логику и что там на самом деле с админкой и DRF.
#django #посмотреть
Рассмотрели нужность батареек, как правильно писать логику и что там на самом деле с админкой и DRF.
#django #посмотреть
YouTube
Как и зачем начинать проекты на Django в 2021 году / Фёдор Борщёв
Приглашаем на Moscow Python Conf 2023, которая пройдет 19 и 20 мая 2023 в Москве в рамках Positive Hack Days.
Программа, подробности и билеты по ссылке https://conf.python.ru/moscow/2023
--------
Moscow Python Conf++ 2021
Профессиональная конференция для…
Программа, подробности и билеты по ссылке https://conf.python.ru/moscow/2023
--------
Moscow Python Conf++ 2021
Профессиональная конференция для…
Один из моих любимых докладов о том, почему вам не нужен асинхронный ORM.
В докладе автор рассказывает про то, что происходит под капотом у асинхронной алхимии, поэтому рекомендуется к просмотру тем, кто пишет бекенд.
#sqlalchemy #посмотреть
В докладе автор рассказывает про то, что происходит под капотом у асинхронной алхимии, поэтому рекомендуется к просмотру тем, кто пишет бекенд.
#sqlalchemy #посмотреть
YouTube
Почему вам не нужен асинхронный ORM / Денис Катаев
Приглашаем на Moscow Python Conf 2023, которая пройдет 19 и 20 мая 2023 в Москве в рамках Positive Hack Days.
Программа, подробности и билеты по ссылке https://conf.python.ru/moscow/2023
--------
Moscow Python Conf++ 2021
Профессиональная конференция для…
Программа, подробности и билеты по ссылке https://conf.python.ru/moscow/2023
--------
Moscow Python Conf++ 2021
Профессиональная конференция для…
Оказывается в конце апреля urllib3 обновили до 2.0.0, который делали аж с 2020 года. Из очень годного:
1) Сделали функцию
2) Упростили работу с json, теперь все выглядит следующим образом:
3) Тайпинги! Хотя, было бы странно видеть такого вида библиотеку без тайпингов в 2023 году.
Плюс ко всему команда описала, с какими проблемами они столкнулись когда добавляли тайпинги, почитать здесь.
Ссылка на новость
1) Сделали функцию
urllib3.request()
, прям как в всеми любимом requests
. Теперь работать с ним можно следующим образом:response = urllib3.request("GET", "https://example.com")И никаких тебе больше
urlopen
.2) Упростили работу с json, теперь все выглядит следующим образом:
resp = urllib3.request(Всё как у
"POST", "https://httpbin.org/anything",
# Параметр json здесь заэнкодит json в body запроса
# и установит 'Content-Type' в 'application/json'.
json={"key": "value"}
)
# а вот так теперь можно получить наш жсончк c ответа
print(resp.json())
requests
, всё как у людей.3) Тайпинги! Хотя, было бы странно видеть такого вида библиотеку без тайпингов в 2023 году.
Плюс ко всему команда описала, с какими проблемами они столкнулись когда добавляли тайпинги, почитать здесь.
Ссылка на новость
Docker 4.19 теперь поддерживает python в docker init
docker init - это утилита, которая упрощает добавление docker в проект. Она просто пробежит по вопросам, спросит версию проекта, какой командой он запускается и сгенерирует Dockerfile и compose-файл.
Мелочь, а приятно :)
#docker
docker init - это утилита, которая упрощает добавление docker в проект. Она просто пробежит по вопросам, спросит версию проекта, какой командой он запускается и сгенерирует Dockerfile и compose-файл.
Мелочь, а приятно :)
#docker
Docker Documentation
docker init
Попался на глаза отличный перевод статьи "Writing Python like it's Rust", который скорее говорит о возможностях аннотаций типов и структур которые их используют (и еще немного про контекстные менеджеры).
Очень много примеров и очень много полезных советов :)
#статья #хабр
Очень много примеров и очень много полезных советов :)
#статья #хабр
Хабр
Пишем на Python как на Rust
Я начал программировать на Rust несколько лет назад, и это постепенно изменило мой подход к разработке программ на других языках программирования, особенно на Python. До того, как я начал использовать...
Если обычного itertools вам мало, то можно использовать more-itertools.
Эта библиотека добавляет огромное количество функций для работы с итераторами. На практике всеми ими не всегда пользуются, поэтому я выделю некоторые из тех, которые сам использую часто.
Например, вот так можно разделить список на 3 части:
Решим самую частую проблему - перевести список с несколькими уровнями вложенностями в "плоский" список:
PyPI | Документация
#more_itertools #itertools #библиотека #рецепт
Эта библиотека добавляет огромное количество функций для работы с итераторами. На практике всеми ими не всегда пользуются, поэтому я выделю некоторые из тех, которые сам использую часто.
Например, вот так можно разделить список на 3 части:
data = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh"]Вот еще задача. Надо разделить список с элементами по определенному условию. В этом нам поможет
[list(l) for l in divide(3, data)]
# [['first', 'second', 'third'], ['fourth', 'fifth'], ['sixth', 'seventh']]
bucket
:class Cat:По итогу кошки и собаки будут разделены по своему типу на 2 генератора.
pass
class Dog:
pass
shapes = [Cat(), Dog(), Cat(), Dog(), Cat(), Cat()]
result = more_itertools.bucket(shapes, key=lambda x: type(x))
len(list(result[Cat])) # 4
len(list(result[Dog])) # 2
Решим самую частую проблему - перевести список с несколькими уровнями вложенностями в "плоский" список:
iterable = [(1, 2), ([3, 4], [[5], [6]])]А если в плоский список нам нужно вытащить только элементы с первым уровнем вложенности?
list(more_itertools.collapse(iterable)) #[1, 2, 3, 4, 5, 6]
list(more_itertools.collapse(iterable, levels=1)) # [1, 2, [3, 4], [[5], [6]]]А вот так мы можем посмотреть, все ли элементы в коллекции уникальные:
more_itertools.all_unique([1, 2, 3, 4]) # TrueБиблиотека решает очень много типовых проблем, поэтому если научиться ей пользоваться - она сэкономит очень много времени. Возможно, я еще буду писать какие-то рецепты с ней, но это не точно 🌚...
more_itertools.all_unique([1, 2, 1, 4]) # False
PyPI | Документация
#more_itertools #itertools #библиотека #рецепт
PyPI
more-itertools
More routines for operating on iterables, beyond itertools
Как раз сегодня искал фреимворк для организации работы консьюмера RabbitMQ и на глаза попался Propan - декларативный фреимворк для работы с очередями сообщений.
Для чего это нужно? На базе очередей можно построить асинхронную коммуникацию сервисов, а это привет микросервисной архитектуре!
Для сравнения, вот столько кода нам нужно написать, чтобы сделать консьюмер при помощи aio_pika:
Что ещё умеет?
1) Кастить типы сообщений в модельки при помощи Pydantic.
2) Умеет работать с зависимостями (привет DI)
3) Имеет CLI утилитку, которая поможет сгенерировать проект, запустить несколько процессов воркеров, запустить хот-релоад для разработки.
4) А ещё есть огромное количество примеров, как им пользоваться.
5) Бонус - похоже у автора в планах прикрутить AsyncAPI (это как OpenAPI, только для очередей).
На данный момент стабильно работает с RabbitMQ, Redis и Nats. Kafka и SQS в бете, а NatsJs, MQTT, Redis Streams и Pulsar в планах.
Ну и накиньте звёзд автору, выглядит как то, что в будущем выстрелит :)
Github | Документация
#библиотека #propan
Для чего это нужно? На базе очередей можно построить асинхронную коммуникацию сервисов, а это привет микросервисной архитектуре!
Для сравнения, вот столько кода нам нужно написать, чтобы сделать консьюмер при помощи aio_pika:
import asyncioА вот столько с Propan:
import aio_pika
async def main():
connection = await aio_pika.connect_robust(
"amqp://guest:guest@127.0.0.1/"
)
queue_name = "test_queue"
async with connection:
channel = await connection.channel()
queue = await channel.declare_queue(queue_name)
async with queue.iterator() as queue_iter:
async for message in queue_iter:
async with message.process():
print(message.body)
asyncio.run(main())
from propan import PropanApp, RabbitBrokerЧистый кайф, не правда ли? Выглядит просто и понятно.
broker = RabbitBroker("amqp://guest:guest@localhost:5672/")
app = PropanApp(broker)
@broker.handle("test_queue")
async def base_handler(body):
print(body)
Что ещё умеет?
1) Кастить типы сообщений в модельки при помощи Pydantic.
2) Умеет работать с зависимостями (привет DI)
3) Имеет CLI утилитку, которая поможет сгенерировать проект, запустить несколько процессов воркеров, запустить хот-релоад для разработки.
4) А ещё есть огромное количество примеров, как им пользоваться.
5) Бонус - похоже у автора в планах прикрутить AsyncAPI (это как OpenAPI, только для очередей).
На данный момент стабильно работает с RabbitMQ, Redis и Nats. Kafka и SQS в бете, а NatsJs, MQTT, Redis Streams и Pulsar в планах.
Ну и накиньте звёзд автору, выглядит как то, что в будущем выстрелит :)
Github | Документация
#библиотека #propan
GitHub
GitHub - Lancetnik/Propan: Propan is a powerful and easy-to-use Python framework for building event-driven applications that interact…
Propan is a powerful and easy-to-use Python framework for building event-driven applications that interact with any MQ Broker - Lancetnik/Propan
Я знаю на опыте, как иногда не удобно работать с датами и временем в Питоне.
В стандартной библиотеке есть как и большое количество типов данных (date, time, tzinfo, timedelta, relativedelta, ...) так и куча модулей (datetime, time, calendar, dateutil, ...) которые помогают работать с ними. Но содержать в голове, да еще и уметь работать с ними иногда проблематично.
Одна из библиотек, которая облегчает работу с сабжем - arrow. Давайте покажу на практике, насколько с ней удобно работать:
1) Получение времени
Начнём с легкого - получим время по MSK и UTC:
Например, вот так можно заменить час в исходной дате:
Возьмем задачу. Нам нужно сказать, через сколько мы прибудем домой. Делается это так:
Как раз недавно решал следующую задачку: дается временной промежуток, для него нужно сделать почасовые интервалы. С arrow всё это делается вот так:
GitHub | Документация
#библиотека
В стандартной библиотеке есть как и большое количество типов данных (date, time, tzinfo, timedelta, relativedelta, ...) так и куча модулей (datetime, time, calendar, dateutil, ...) которые помогают работать с ними. Но содержать в голове, да еще и уметь работать с ними иногда проблематично.
Одна из библиотек, которая облегчает работу с сабжем - arrow. Давайте покажу на практике, насколько с ней удобно работать:
1) Получение времени
Начнём с легкого - получим время по MSK и UTC:
>>> arrow.now() # получаем текущее время по MSKА если нам надо текущее время с другой таимзоной?
2023-06-02T18:46:55.188882+03:00
>>> arrow.utcnow() # а теперь текущее, но в UTC
2023-06-02T15:46:55.188882+00:00
>>> arrow.get().to("US/Pacific")Это было просто. А что если нам нужно спарсить время из шаблона?
2023-06-02T08:49:39.794355-07:00
>>> arrow.get('2023/06-02|19:00:{00}', 'YYYY/MM-DD|HH:mm:{ss}') #обратите внимание на шаблон!Ещё arrow позволяет искать даты в строке по шаблону:
2023-06-02T19:00:00+00:00
>>>arrow.get('Он родился 16 Мая 2020 года', 'DD MMMM YYYY', locale="ru")2) Работа со временем
2020-05-16T00:00:00+00:00
Например, вот так можно заменить час в исходной дате:
>>>arrow.now().replace(hour=12)Или добавить к текущей дате +5 недель:
2023-06-02T12:00:29.180755+03:00
>>>arrow.now().shift(weeks=+5)Ну и в конце, давайте отформатируем текущее время в строку по шаблону:
2023-07-07T19:02:27.174819+03:00
>>>arrow.now().format('YYYY HH:mm:ss MM/DD')3) Очеловечивание времени
2023 19:05:04 06/02
Возьмем задачу. Нам нужно сказать, через сколько мы прибудем домой. Делается это так:
>>> start_time = arrow.now()А если мы хотим из человеческого формата перевести в машинночитаемый?
>>> arrive_time = start_time.shift(hours=+3, minutes=10, seconds=12)
>>> humanized = arrive_time.humanize(locale="ru", granularity=["hour", "minute", "second"])
>>> print(f"Вы прибудете домой {humanized}")
Вы прибудете домой через 3 часа 10 минут 12 секунд
>>> start_time.dehumanize(humanized, locale="ru")4) Работа с диапазонами
2023-06-02T22:28:08.141525+03:00
Как раз недавно решал следующую задачку: дается временной промежуток, для него нужно сделать почасовые интервалы. С arrow всё это делается вот так:
start = datetime(2023, 1, 1, 00, 00)В любом случае, рекомендую присмотреться, возможно для вас эта библиотека станет одним еще довольно удобным инструментом!
end = datetime(2023, 1, 1, 23, 00)
for r in arrow.Arrow.span_range('hour', start, end):
print(r)
(<Arrow [2023-01-01T00:00:00+00:00]>, <Arrow [2023-01-01T00:59:59.999999+00:00]>)
....
(<Arrow [2023-01-01T23:00:00+00:00]>, <Arrow [2023-01-01T23:59:59.999999+00:00]>)
GitHub | Документация
#библиотека
GitHub
GitHub - arrow-py/arrow: 🏹 Better dates & times for Python
🏹 Better dates & times for Python. Contribute to arrow-py/arrow development by creating an account on GitHub.
Если у вас есть желание понять как работает asyncio, threading или multiprocessing, либо же появились вопросы - рекомендую обратить внимание на superfastpython.com
Автор понятным языком рассказывает про доступные формы параллелизма и где какую можно применить. Для совсем начинающих он сделал "пути обучения", где раскиданы темы по каждой из форм.
Для особо искушенных автор продает книги по разным темам, но как по мне они в какой-то мере повторяют бесплатный материал, который уже есть на сайте.
Практически каждая статья сопровождается реальными примерами, которые можно самому запустить.
Все материалы на английском, но некоторые из них переводит на русский комьюнити (например цикл статей про asyncio).
#asyncio #threading #multiprocessing #статья
Автор понятным языком рассказывает про доступные формы параллелизма и где какую можно применить. Для совсем начинающих он сделал "пути обучения", где раскиданы темы по каждой из форм.
Для особо искушенных автор продает книги по разным темам, но как по мне они в какой-то мере повторяют бесплатный материал, который уже есть на сайте.
Практически каждая статья сопровождается реальными примерами, которые можно самому запустить.
Все материалы на английском, но некоторые из них переводит на русский комьюнити (например цикл статей про asyncio).
#asyncio #threading #multiprocessing #статья
Super Fast Python
Home - Super Fast Python
Master Python concurrency super fast. Learn threading, multiprocessing, and asyncio with step-by-step books and code tutorials.
Создание временных файлов
В процессе написания скрипта может потребоваться создание временных файлов, которые будут удалены автоматически после завершения работы скрипта или обработки файла.
Это может быть полезно по разным причинам - при обработке больших данных (которые не вместятся в буфер) или при проведении сложных операций (например, можно создать временный файл и натравить на него ffmpeg).
Для решения этих проблем в Python есть модуль
В процессе написания скрипта может потребоваться создание временных файлов, которые будут удалены автоматически после завершения работы скрипта или обработки файла.
Это может быть полезно по разным причинам - при обработке больших данных (которые не вместятся в буфер) или при проведении сложных операций (например, можно создать временный файл и натравить на него ffmpeg).
Для решения этих проблем в Python есть модуль
tempfile
. Нас интересует 2 функции - это TemporaryFile
и NamedTemporaryFile
.TemporaryFile
позволяет создать безымянный временный файл. Вот так можно создать временный текстовой файл, открыть его на запись и чтение (за это отвечает первый аргумент "w+t"
, подробнее можно прочитать здесь):from tempfile import TemporaryFile
with TemporaryFile("w+t") as t:
t.write("Hello, boxwithpython!")
t.seek(0)
data = t.read()
NamedTemporaryFile
используется для более продвинутых сценариев, так как он создает файл с именем, поэтому мы можем получить путь к нему и использовать его для дальнейших целей:from tempfile import
NamedTemporaryFile
with NamedTemporaryFile("w+t") as t:#std
t.write("Hello, boxwithpython!")
print(t.name) # /tmp/tmpljhsktjt