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

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

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

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

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

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

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, чтобы получить результат сопрограммы. Он будет ждать завершения сопрограммы.

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

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

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

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

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

Ссылки

Last updated

Was this helpful?