TL;DR 要获取事件循环,请调用asyncio.get_event_loop()
.
在基于 asyncio 的应用程序中,事件循环通常不属于 Quart 或任何其他协议/应用程序级别的组件,它由 asyncio 或可能的加速器(如 uvloop)提供。事件循环是通过调用获得的asyncio.get_event_loop()
,有时也用asyncio.set_event_loop()
.
这是 quartapp.run()
用来运行应用程序的,这意味着它可以与 asyncio 为主线程创建的默认事件循环一起工作。run()
在您的情况下,您可以在注册后简单地调用 quart 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()