เข้าถึง app_context จากงานอื่นใน Quart

แอป My 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 คำขอ ฯลฯ... โปรดทราบว่าบริบทเหล่านี้เป็นงานภายในเครื่อง และด้วยเหตุนี้จะไม่มีอยู่หากงานถูกสร้างขึ้นโดย 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 ถูกคัดลอกไปยังงานที่สร้างขึ้นจากงานที่มีบริบทของแอปโดยอัตโนมัติ เหตุใดตัวอย่างของฉันจึงไม่ทำงาน

รอ 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