Запуск цикла событий Asyncio в другом потоке

Оригинал статьи: https://www.linw1995.com/en/blog/Run-Asyncio-Event-Loop-in-another-thread/arrow-up-right

Дата публикации: 14 марта 2020

Запуск цикла событий asyncio в другом потоке

При использовании веб-фреймворка, который не поддерживает запись параллельного кода с использованием синтаксиса async/await, вы хотите использовать concurrent для ускорения соединения с другой службой, например, подключение Redis, выполнение большого количества запросов и т. д. Итак, вот почему нам нужно запускать цикл событий asyncio в другом потоке.

Создание потока, который запускает цикл событий asyncio навсегда

circle-exclamation
import asyncio
import threading

class AsyncioEventLoopThread(threading.Thread):
    def __init__(self, *args, loop=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.loop = loop or asyncio.new_event_loop()
        self.running = False

    def run(self):
        self.running = True
        self.loop.run_forever()

    def run_coro(self, coro):
        return asyncio.run_coroutine_threadsafe(coro, loop=self.loop).result()

    def stop(self):
        self.loop.call_soon_threadsafe(self.loop.stop)
        self.join()
        self.running = False

Поскольку функция asyncio.run_coroutine_threadsafe возвращает объект concurrent.futures.Future, мы просто выполняем метод result, чтобы получить результат сопрограммы. Он будет ждать завершения сопрограммы.

Ниже приведен простой пример, демонстрирующий как его использовать.

circle-exclamation

Совместное использование объектов между сопрограммами

Вы должны унаследовать AsyncioEventLoopThread или просто изменить его, чтобы хранить объекты, которые необходимо совместно использовать между сопрограммами.

Используя contextvars для совместного использования объектов между сопрограммами, общие значения должны быть сохранены в contextvars.Context перед запуском сопрограмм.

Ниже приведен простой пример получения исходного кода веб-сайта github.com.

Ссылки

Last updated