Запуск цикла событий 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?