Доступ к app_context из другой задачи в Quart

Мое приложение 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 и т. д. Обратите внимание, что эти контексты являются локальными для задачи и, следовательно, не будут существовать, если задача порождена с помощью sure_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()

моя функция обратного вызова находится в другом модуле, и я перехожу к стороннему экземпляру:

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 автоматически копируется в созданные задачи из задачи с контекстом приложения, почему мой пример не работает?

await Third_Party.start() внутри оператора with app_context вызывает loop.create_task(run()), который запускает назначенную мне функцию обратного вызова. Так почему же внутри этого обратного вызова нет доступного app_context?


person Eric    schedule 19.01.2020    source источник


Ответы (1)


Я думаю, вы должны использовать версию Quart 0.6.X? Если да, то 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, см. ошибку.

person pgjones    schedule 19.01.2020
comment
Большое спасибо, что уделили время ответу. Не могли бы вы еще раз взглянуть на мою правку? Я использую Quart 0.10.0, и, насколько я понимаю, контекст приложения должен быть скопирован в мою созданную задачу. Спасибо за Quart кстати :) - person Eric; 20.01.2020