aiomisc - это библиотека с различными утилитами для asyncio#
Вам, как программисту, знакомы проблемы, связанные с дизайном и обслуживанием программ. Одним из мест, которое может быть особенно сложным, является создание архитектуры программы, использующего асинхронный ввод-вывод.
Вот тут на сцену выходит aiomisc
. Это библиотека Python, которая предоставляет набор служебных функций и классов для работы с асинхронным IO более интуитивно понятным и эффективным способом. Она построена используя библиотеку asyncio и предназначена для облегчения написания асинхронного кода разработчиками, который является надежным и масштабируемым.
С aiomisc вы можете воспользоваться такими мощными функциями, как: worker пул, connection пул, шаблон «предохранитель», и механизмы повторов такие как asyncbackoff и asyncretry чтобы сделать ваш асинхронный код более надежным и простым в обслуживании. В этой документации мы более подробно рассмотрим, что может предложить aiomisc
и как он может помочь вам упростить разработку сервисов с asyncio.
Установка#
Возможна установка стандартными способами, такими как PyPI или установка из репозитория git напрямую.
Установка с PyPI:
pip3 install aiomisc
Установка из репозитория на github.com:
# Using git tool
pip3 install git+https://github.com/aiokitchen/aiomisc.git
# Alternative way using http
pip3 install \
https://github.com/aiokitchen/aiomisc/archive/refs/heads/master.zip
Пакет содержит несколько дополнений, и вы можете установить дополнительные зависимости, если вы укажете их таким образом.
Вместе с uvloop
pip3 install "aiomisc[uvloop]"
Вместе с aiohttp:
pip3 install "aiomisc[aiohttp]"
Полная таблица дополнений ниже:
пример |
описание |
---|---|
|
Для запуска приложений написанных с aiohttp. |
|
Для запуска ASGI приложений |
|
|
|
планирование задач с библиотекой croniter |
|
|
|
Можете использовать rich для логирования |
|
|
|
используйте uvloop как основной event-loop |
Вы можете комбинировать эти значения разделяя их запятыми, пример:
pip3 install "aiomisc[aiohttp,cron,rich,uvloop]"
Быстрый старт#
В этом разделе будет рассказано, как эта библиотека создает и использует цикл обработки событий и создает службы. Конечно, обо всем тут не напишешь, но о многом можно прочитать в разделе Учебник, и всегда можно обратиться к разделу Модули и разделу Описание API для справки.
Eventloop и entrypoint#
Сначала рассмотрим этот простой пример:
import asyncio
import logging
import aiomisc
log = logging.getLogger(__name__)
async def main():
log.info('Starting')
await asyncio.sleep(3)
log.info('Exiting')
if __name__ == '__main__':
with aiomisc.entrypoint(log_level="info", log_format="color") as loop:
loop.run_until_complete(main())
Этот код объявляет асинхронную функцию main()
, которая завершается через 3 секунды. Казалось бы, ничего интересного, но все дело в entrypoint
.
Что делает entrypoint
, казалось бы не так уж и много, она создает event-loop и передает управление пользователю. Однако под капотом настраивается журналирование в отдельном потоке, создается пул потоков, запускаются сервисы, но об этом позже и сервисов в данном примере нет.
В принципе вы можете не использовать точку входа, а просто создать eventloop и установите его по умолчанию для текущего потока:
import asyncio
import aiomisc
# * Installs uvloop event loop is it's has been installed.
# * Creates and set `aiomisc.thread_pool.ThreadPoolExecutor`
# as a default executor
# * Sets just created event-loop as a current event-loop for this thread.
aiomisc.new_event_loop()
async def main():
await asyncio.sleep(1)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Приведенный выше пример полезен, если в вашем коде уже неявно используется созданный eventloop, тогда вам придется изменить меньше кода, просто добавьте aiomisc.new_event_loop()
и все вызовы asyncio.get_event_loop()
вернет созданный экземпляр.
Однако можно обойтись и одним вызовом. Следующий пример закрывает неявно созданный eventloop asyncio и устанавливает новый:
import asyncio
import aiomisc
async def main():
await asyncio.sleep(3)
if __name__ == '__main__':
loop = aiomisc.new_event_loop()
loop.run_until_complete(main())
Сервисы#
Главное, что делает точка входа, — это запускает и корректно останавливает «Сервисы».
Концепция «Сервис», в этой библиотеке, означает класс, наследованный от класса aiosmic.Service
и реализующий метод async def start(self) -> None
и, опционально, метод async def stop(self, exc: Optional[ Exception]) -> None
.
Концепция остановки службы не обязательно заключается в нажатии пользователем клавиш Ctrl+C
, на самом деле это просто выход из контекстного менеджера entrypoint
.
Пример ниже иллюстрирует, как может выглядеть ваш сервис:
from aiomisc import entrypoint, Service
class MyService(Service):
async def start(self):
do_something_when_start()
async def stop(self, exc):
do_graceful_shutdown()
with entrypoint(MyService()) as loop:
loop.run_forever()
Точка входа может запускать любое количество экземпляров службы, и все они будут запускаться конкурентно.
Также есть способ, если метод start
является полезной нагрузкой для сервиса, и тогда нет необходимости реализовывать метод stop
, так как задача с функцией start
будет отменена на этапе выхода из entrypoint. Но в этом случае вам придется уведомить entrypoint
о том, что инициализация экземпляра службы завершена и ее можно продолжить.
Примерно так:
import asyncio
from threading import Event
from aiomisc import entrypoint, Service
event = Event()
class MyService(Service):
async def start(self):
# Send signal to entrypoint for continue running
self.start_event.set()
await asyncio.sleep(3600)
with entrypoint(MyService()) as loop:
assert event.is_set()
Примечание
entrypoint
передает управление телу контекстного менеджера только после того, как все экземпляры службы запущены. Как упоминалось выше, стартом считается завершение метода start
или установка стартового события с помощью self.start_event.set()
.
Вся мощь этой библиотеки это набор уже реализованных или абстрактных сервисов таких как: AIOHTTPService, ASGIService, TCPServer, UDPServer, TCPClient, PeriodicService, CronService и так далее.
К сожалению в данном разделе нет возможности уделить этому больше внимания, обратите внимание на раздел Учебник, там больше примеров и пояснений, ну и конечно вы всегда можете узнать ответ на Описание API или в исходном коде. Авторы постарались сделать исходный код максимально понятным и простым, поэтому не стесняйтесь исследовать его.
Версионирование#
Это программное обеспечение следует методологиии Семантического Версионирования
Кратко: учитывая номер версии МАЖОРНАЯ.МИНОРНАЯ.ПАТЧ, следует увеличивать:
МАЖОРНУЮ версию, когда сделаны обратно несовместимые изменения API.
МИНОРНУЮ версию, когда вы добавляете новую функциональность, не нарушая обратной совместимости.
ПАТЧ-версию, когда вы делаете обратно совместимые исправления.
Дополнительные обозначения для предрелизных и билд-метаданных возможны как дополнения к МАЖОРНАЯ.МИНОРНАЯ.ПАТЧ формату.
В этом проекте версия пакета назначается автоматически с помощью poem-plugins, он использует тег в репозитории как МАЖОР и МИНОР, а также счетчик, который берет количество коммитов между тегом и головой ветки.
Как разрабатывать этот проект?#
Этот проект, как и многие другие open source проекты, разрабатывается энтузиастами, и вы можете присоединиться к разработке, создавайте issues в github или присылайте свои правки как merge request.
Чтобы начать разработку в этом репозитории, вам необходимо сделать следующее:
Должно быть установлено
Python 3.7+ как
python3
Установлен Poetry как
poetry
Для настройки окружения разработчика выполните:
# installing all dependencies poetry install # setting up pre-commit hooks poetry run pre-commit install # adding poem-plugins to the poetry poetry self add poem-plugins
- 1. Учебник
- 2. Модули
- 2.1. Точка входа (entrypoint)
- 2.2. Функция
run()
- 2.3. Конфигурация журналов
- 2.4. Сервисы
- 2.4.1. Класс
TCPServer
- 2.4.2. Класс
UDPServer
- 2.4.3. Класс
TLSServer
- 2.4.4.
TCPClient
- 2.4.5.
TLSClient
- 2.4.6.
RobustTCPClient
- 2.4.7.
RobustTLSClient
- 2.4.8. Класс
PeriodicService
- 2.4.9. DNS Server
- 2.4.10. Класс
CronService
- 2.4.11. Несколько сервисов
- 2.4.12. Конфигурация
- 2.4.13. aiohttp сервис
- 2.4.14. asgi сервис
- 2.4.15. uvicorn service
- 2.4.16. GRPC service
- 2.4.17. Трассировщик памяти
- 2.4.18.
Profiler
- профилировщик - 2.4.19. Raven сервис
- 2.4.20.
SDWatchdogService
- 2.4.21. Класс
ProcessService
- 2.4.22. Класс
RespawningProcessService
- 2.4.1. Класс
- 2.5. Абстрактный пул соединений
- 2.6. Контекст
- 2.7.
@aiomisc.timeout
- 2.8.
@aiomisc.asyncbackoff
- 2.9.
asyncretry
- 2.10. Предохранитель
- 2.11. Декоратор
cutout
- «рубильник» - 2.12.
@aiomisc.aggregate
- 2.13. асинхронные операции с файлами
- 2.14. Работа с потоками
- 2.15.
ProcessPoolExecutor
- 2.16. Утилиты
- 2.17.
WorkerPool
- 2.18. Конфигурация логирования
- 2.19. Плагин для Pytest
- 2.20.
Signal
- 2.21. Plugins
- 2.22. Статистические счетчики
- 3. Описание API
- 3.1. Модуль
aiomisc
- 3.1.1. Модуль
aiomisc.aggregate
- 3.1.2. Модуль
aiomisc.backoff
- 3.1.3. Модуль
aiomisc.circuit_breaker
- 3.1.4. Модуль
aiomisc.compat
- 3.1.5. Модуль
aiomisc.context
- 3.1.6. Модуль
aiomisc.counters
- 3.1.7. Модуль
aiomisc.cron
- 3.1.8. Модуль
aiomisc.entrypoint
- 3.1.9. Модуль
aiomisc.io
- 3.1.10. Модуль
aiomisc.iterator_wrapper
- 3.1.11. Модуль
aiomisc.log
- 3.1.12. Модуль
aiomisc.periodic
- 3.1.13. Модуль
aiomisc.plugins
- 3.1.14. Модуль
aiomisc.pool
- 3.1.15. Модуль
aiomisc.process_pool
- 3.1.16. Модуль
aiomisc.recurring
- 3.1.17. Модуль
aiomisc.signal
- 3.1.18. Модуль
aiomisc.thread_pool
- 3.1.19. Модуль
aiomisc.timeout
- 3.1.20. Модуль
aiomisc.utils
- 3.1.21. Модуль
aiomisc.worker_pool
- 3.1.1. Модуль
- 3.2. Модуль
aiomisc_log
- 3.3. Модуль
aiomisc_worker
- 3.1. Модуль