如何从 Quart 获取事件循环
How to obtain an event loop from 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 之上构建的。
有谁知道我怎样才能得到它?任何帮助将不胜感激。
TL;DR 要获取事件循环,请调用 asyncio.get_event_loop()
.
在 asyncio-based 应用程序中,事件循环通常不属于 Quart 或任何其他 protocol/application 级组件,它由 asyncio 或可能像 uvloop 这样的加速器提供。事件循环通过调用asyncio.get_event_loop()
获得,有时设置为asyncio.set_event_loop()
.
这就是 quart 的 app.run()
用于 运行 应用程序的方式,这意味着它与 asyncio 为主线程创建的默认事件循环一起工作。在您的情况下,您可以在注册 Goblin
:
后简单地调用 quart 的 run()
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()
不会 return,您只能调用一个这样的方法在线程中运行。
不过,如果您仔细观察,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()
你好,我是 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 之上构建的。
有谁知道我怎样才能得到它?任何帮助将不胜感激。
TL;DR 要获取事件循环,请调用 asyncio.get_event_loop()
.
在 asyncio-based 应用程序中,事件循环通常不属于 Quart 或任何其他 protocol/application 级组件,它由 asyncio 或可能像 uvloop 这样的加速器提供。事件循环通过调用asyncio.get_event_loop()
获得,有时设置为asyncio.set_event_loop()
.
这就是 quart 的 app.run()
用于 运行 应用程序的方式,这意味着它与 asyncio 为主线程创建的默认事件循环一起工作。在您的情况下,您可以在注册 Goblin
:
run()
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()
不会 return,您只能调用一个这样的方法在线程中运行。
不过,如果您仔细观察,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()