0

我的 Quart 应用程序是使用 create_app 工厂方法创建的。

我还通过 create_task 方法将第三方库合并为附加任务。

我将一个回调函数传递给这个库,它更新我的数据库(通过 SQLAlchemy)。不幸的是,这不起作用并引发异常:

“尝试在相关上下文之外访问应用程序”

推送应用上下文不起作用:

from quart import current_app as app

async with app.app_context():

查看 Quarts 上下文文档:https ://pgjones.gitlab.io/quart/contexts.html 原因很明显,因为第三方任务中不存在该应用程序。

每个请求都存在这两个上下文,并允许解析全局代理 current_app、request 等。请注意,这些上下文是任务本地的,因此如果任务是由 ensure_future 或 create_task 生成的,则这些上下文将不存在。

有没有人有任何其他解决方案来从另一个任务中获取应用程序上下文?

编辑 它仍然不起作用。我正在使用夸脱 0.10.0。我的应用程序的一个更详细的示例如下所示:

from app import create_app

from third_party import ThirdParty

third_party = ThirdParty(loop=asyncio.get_event_loop())
app = create_app()

@app.before_serving
async def startup():
    async with app.app_context() as app_context:
        await third_party.start()


@app.after_serving
async def shutdown():
    await third_party.stop()


if __name__ == "__main__":
    app.run()

第三方基本上是这样的:

class ThirdParty:
    async def start(self):
        self.loop.create_task(self.run())

    async def run(self):
        while True:
            await self.wait_for_trigger()
            # executes my callback function
            await self.custom_callback_func()

我的回调函数在另一个模块中,我传递给 third_party 实例:

from quart import current_app as app

async def custom_callback_func():
    async with app.app_context:
        # update_my database
        # raises "Attempt to access app outside of a relevant context"

如果 app_context 自动从具有应用上下文的任务复制到创建的任务,为什么我的示例不起作用?

在 with app_context 语句中的 await third_party.start() 调用 loop.create_task(run()) ,它运行我分配的回调函数。那么为什么这个回调中没有 app_context 可用呢?

4

1 回答 1

1

我认为您必须使用 0.6.X 版本的 Quart?如果是这样,copy_current_app_context(来自 quart.ctx)可用于将上下文显式复制到新任务中。例如,

task = asyncio.ensure_future(copy_current_app_context(other_task_function)())

另请参阅这个简短的文档片段。请注意,它是用 Quart >= 0.7 编写的,它应该会自动复制任务之间的上下文。

编辑: 在更新问题之后。

我认为你最好传递app实例并直接使用它,而不是current_app在任务中使用。before_serving这是因为在第一个请求之后和之前没有应用上下文。不过,这可能会在 Quart 中发生变化,请参阅此问题

于 2020-01-19T12:56:19.203 回答