Как получить цикл событий из 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()
Другие вопросы по тегам