Всем привет, меня зовут Олег, я старший бэкенд разработчик, а также по совместительству ментор бэкенда в команде Sapphire в Битве пет-проектов. Вот уже на протяжении 10 лет Python является моим основным языком программирования. В нашей компании, где я работаю над проектом для бессерверных вычислений, Python также  - основной язык программирования (наряду с Go). Одним из корпоративных стандартов является внутренний обмен информацией по протоколу gRPC. Причины просты - данных огромное количество, нагрузка на сеть колоссальная, отсюда и потребность в экономии размера передаваемых данных. gRPC (Remote Procedure Calls) — это система удалённого вызова процедур (RPC) с открытым исходным кодом, первоначально разработанная в Google в 2015 году. В качестве транспорта используется HTTP/2, в качестве языка описания интерфейса — Protocol Buffers. gRPC предоставляет такие функции как аутентификация, двунаправленная потоковая передача и управление потоком, блокирующие или неблокирующие привязки, а также отмена и тайм-ауты. Генерирует кроссплатформенные привязки клиента и сервера для многих языков. Чаще всего используется для подключения служб в микросервисном стиле архитектуры и подключения мобильных устройств и браузерных клиентов к серверным службам. Протокол gRPC в данный момент является довольно распространённым решением (почему, очень хорошо описано в статье от Яндекса). На работе мы также используем его везде, где идёт речь об общении микросервисов друг с другом. Но, к сожалению, когда я начал вникать в устройство и применять его, то столкнулся с крайне сложным процессом имплементации gRPC сервиса на Python.  Для начала надо освоить protocol buffers и составить корректный .proto файл, чтобы описать интерфейс будущего gRPC сервиса. Потом с помощью Python библиотеки Protobuf нужно на основе .proto файлов сгенерировать Python модули (pb2.py и pb2_grpc.py). Позже надо подключить сгенерированные модули к вашему приложению (возможно, построить абстракции над ними или использовать напрямую). А, да, при этом сгенерированные модули практически не читабельны и потребуют модификации (как минимум потому что там могут быть некорректно указаны импорты, как максимум - линтеры не пропустят). Да, gRPC является более сложным протоколом по своей структуре (хотя бы потому что он не текстовый и передаваемые пакеты нельзя просто открыть и прочитать), но при этом сам он для понимания является более простым. Объясню, почему я так в этом уверен. Для полноценного использования HTTP вам нужно обязательно знать: Какими методами можно выполнить запрос (GET, POST, PATCH, PUT, ...). С какими статус кодами может вернуться ответ и что они означают (200, 403, 502, ...). Как сформировать путь к странице. Какие бывают протоколы и в чём их отличие (http, https). Заголовки запроса и ответа (какие бывают, что означают). Зачем Query параметры и для чего их используют. А ещё структура запроса отличается от структуры ответа. А если говорить ещё и о REST, то он тоже добавляет требования поверх всего этого списка. Таким образом, порог входа в работу с HTTP и REST оказывается довольно высоким, но при этом это стандартный протокол: фреймворков для построения веб-приложений - тьма, обучающих материалов - море, Quick Start-ов по созданию собственного веб-сервиса - выше крыши. В gRPC же всё сведено к простому: методов как таковых нет (по факту используется только POST), путей тоже нет (вместо них используются определённые в .proto файле rpc), понятия протокола тоже нет (достаточно указать - secure или insecure), query параметры тоже отсутствуют. Но при этом написать сервер на gRPC на Python в разы сложнее, чем реализовать REST API интерфейс. Просто посмотрите на минимально рабочий пример реализации REST API на Python на фреймворке FastAPI: Очень просто, не правда ли? А вот для работы с gRPC на Python нужно выполнить все шаги, которые я описал выше. И кстати, при изменении интерфейса в .proto файле путь надо будет пройти снова. Такой процесс делает работу с gRPC нереально сложной для новичков. В рамках Битвы пет-проектов мы в Sapphire тоже нашли потребность в общении сервисов между собой. Изначально для этого у нас была Kafka, но она точно не подходит для получения информации от другого сервиса. Мы могли бы использовать REST (вряд ли у нас будет высокая нагрузка на внутреннюю сеть), но так как у меня есть опыт работы с gRPC на работе, то реализовать gRPC интерфейс показалось хорошей идеей. Но когда дело дошло до реализации, оказалось что реализовать сервис с нуля сложно и он будет выглядеть крайне громоздко, требуя написания большего количества кода, чем весь реализованный REST API. Поэтому в процессе изучения я решил поискать готовые решения, которые бы упрощали реализацию gRPC сервиса на Python. Конечно же, я их нашёл: Fast-GRPC - классный асинхронный фреймворк. Мне он понравился, но было несколько проблем: использования старого pydantic (что я изменил в форке) и баги (например, в метод, который обрабатывает запрос, в self передаётся значение None). В принципе именно эти баги и заставили от него отказаться, так как ковыряться в запутанной структуре оказалось сложно и требовало много времени. grpcalchemy - классный синхронный фреймворк. Он тоже понравился, но его проблемой было то, что он только синхронный, а реализация асинхронного сервера уже давно висит в TODO. Я попытался его реализовать, но встроить его в существующую систему оказалось сложнее, чем я думал. Остальное из awesome-grpc - я просмотрел всё и из подходящих оставалась только библиотека grpclib, которая хоть и не обладала проблемами вышеперечисленных, но и реализацию не делала простой. После двухдневных поисков и проб я потерял веру в то, что найду подходящий инструмент и решил, что пришло время реализовать свою имплементацию. Встречайте: Fast-gRPC (да, я не придумал ничего лучше). Установить довольно просто: А минимальная имплементация сервера выглядит так: Как видите, здесь пропущены шаги с составлением proto файла, с генерацией pb2 и pb2_grpc модулей, с их подключением к проекту, всё это работает под капотом сервиса, программисту нужно только описать pydantic модели для запроса и ответа. Дополнительно можно указать имя сервиса, название каждого метода, порт сервера и включить рефлексию, но по умолчанию о них можно не задумываться. Все proto, pb2 и pb2_grpc файлы, которые нужны для работы сервера, генерируются в корне проекта, но это также можно изменить, указав нужные директории в аргументах сервиса. К сожалению, в моделях запросов и ответов сейчас поддерживаются только стандартные Python типы данных (не включая коллекции, такие как list и dict) и uuid (то что сейчас требовалось в рамках Битвы пет-проектов), но в дальнейшем я предполагаю расширение возможностей. Даёшь простой gRPC на Python всем! P.S. Кстати, я также веду некоторые свои соцсети, в которых рассказываю о Python, об IT и вообще о жизни - VK и Telegram.  Senior Python Developer