Как получить цикл событий из Quart
Здравствуйте, я довольно новичок в Python и пытаюсь преобразовать существующее у меня приложение на Flask в Quart ( https://gitlab.com/pgjones/quart), который должен быть построен поверх asyncio, поэтому я могу использовать Goblin OGM для взаимодействия с JanusGraph или TinkerPop. В соответствии с примерами, которые я нашел на Goblin, мне нужно получить цикл обработки событий для асинхронного выполнения команд.
>>> import asyncio
>>> from goblin import Goblin
>>> loop = asyncio.get_event_loop()
>>> app = loop.run_until_complete(
... Goblin.open(loop))
>>> app.register(Person, Knows)
Однако я не могу найти способ получить цикл событий из Quart, даже если он построен поверх asyncio.
Кто-нибудь знает, как я могу получить это? Любая помощь будет высоко оценена.
1 ответ
TL;DR Чтобы получить цикл обработки событий, позвоните asyncio.get_event_loop()
,
В приложении, основанном на асинхронном программировании, цикл обработки событий, как правило, не принадлежит Quart или любому другому компоненту уровня протокола / приложения, он предоставляется Asyncio или, возможно, ускорителем, таким как uvloop. Цикл событий получается путем вызова asyncio.get_event_loop()
и иногда устанавливается с asyncio.set_event_loop()
,
Это то, что кварта app.run()
используется для запуска приложения, что означает, что оно работает с циклом событий по умолчанию, созданным asyncio для основного потока. В вашем случае вы можете просто позвонить Quart's run()
после регистрации Goblin
:
loop = asyncio.get_event_loop()
goblin_app = loop.run_until_complete(Goblin.open(loop))
goblin_app.register(Person, Knows)
quart_app = Quart(...)
# ... @app.route, etc
# now they both run in the same event loop
quart_app.run()
Вышесказанное должно дать ответ на вопрос в практическом смысле. Но такой подход не сработал бы, если бы более одного компонента требовали
run()
метод, который раскручивает цикл событий - с app.run()
не возвращается, вы можете вызвать только одну такую функцию в потоке.Если вы посмотрите более внимательно, это не совсем так с quart
или. В то время как примеры Quart действительно используют app.run()
обслуживать приложение, если вы посмотрите на реализацию app.run()
, вы увидите, что он вызывает функцию удобства run_app()
, который тривиально создает сервер и навсегда раскручивает основной цикл:
def run_app(...):
loop = asyncio.get_event_loop()
# ...
create_server = loop.create_server(
lambda: Server(app, loop, ...), host, port, ...)
server = loop.run_until_complete(create_server)
# ...
loop.run_forever()
Если вам нужно контролировать, как на самом деле выполняется цикл обработки событий, вы всегда можете сделать это самостоятельно:
# obtain the event loop from asyncio
loop = asyncio.get_event_loop()
# hook Goblin to the loop
goblin_app = loop.run_until_complete(Goblin.open(loop))
goblin_app.register(Person, Knows)
# hook Quart to the loop
quart_server = loop.run_until_complete(loop.create_server(
lambda: quart.serving.Server(quart_app, loop), host, port))
# actually run the loop (and the program)
try:
loop.run_forever()
except KeyboardInterrupt: # pragma: no cover
pass
finally:
quart_server.close()
loop.run_until_complete(quart_server.wait_closed())
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()