运行同步代码#

同步代码会阻塞事件循环,并降低运行它的 Quart 应用程序的性能。这是因为同步代码会阻塞它运行的任务,还会阻塞事件循环。出于这个原因,最好避免使用同步代码,优先使用异步版本。

不过,您可能需要使用一个同步的第三方库,因为它没有异步版本可以使用。在这种情况下,通常在线程池执行器中运行同步代码,这样它就不会阻塞事件循环,从而不会降低 Quart 应用程序的性能。这可能有点棘手,因此 Quart 提供了一些帮助程序来执行此操作。首先,任何同步路由都会在执行器中运行,例如:

@app.route("/")
def sync():
    method = request.method
    ...

会导致 sync 函数在线程中运行。请注意,您仍然在 上下文 中,因此您仍然可以访问 requestcurrent_app 和其他全局变量。

以下功能接受同步函数,并将它们在线程中运行:

  • 路由处理程序

  • 端点处理程序

  • 错误处理程序

  • 上下文处理器

  • 请求之前

  • WebSocket 之前

  • 第一个请求之前

  • 服务之前

  • 请求之后

  • WebSocket 之后

  • 服务之后

  • 拆卸请求

  • 拆卸 WebSocket

  • 拆卸应用上下文

  • 打开会话

  • 创建空会话

  • 保存会话

上下文用法#

虽然您可以在同步路由中访问 request 和其他全局变量,但您将无法等待协程函数。为了解决这个问题,Quart 提供了 run_sync(),它可以这样使用:

@app.route("/")
async def sync_within():
    data = await request.get_json()

    def sync_processor():
         # does something with data
         ...

    result = await run_sync(sync_processor)()
    return result

这类似于使用 asyncio run_in_executor 函数,

@app.route("/")
async def sync_within():
    data = await request.get_json()

    def sync_processor():
         # does something with data
         ...

    result = await asyncio.get_running_loop().run_in_executor(
        None, sync_processor
    )
    return result

注意

run_in_executor 函数不复制当前上下文,而 run_sync 方法则复制。出于这个原因,建议使用后者。如果没有复制的上下文,request 和其他全局变量将无法访问。