如何在Tornado应用程序中管理资源的异步启动和关闭?

问题描述 投票:1回答:1

我想在Tornado应用程序中使用aioredis。但是,由于Application类没有诸如Quart或FastAPI之类的ASGI Lifespan事件,因此我无法找到实现其资源的异步启动和关闭的方法。换句话说,我需要在应用开始提供请求之前创建Redis池,并在应用完成或即将结束后立即释放该池。问题是aioredis池创建是异步的,但是Tornado应用程序创建是同步的。

基本应用程序看起来像这样:

    import os

from aioredis import create_redis_pool
from aioredis.commands import Redis
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application

from .handlers import hello

redis: Redis = None


async def start_resources() -> None:
    '''
    Initialize resources such as Redis and Database connections
    '''
    global redis
    REDIS_HOST = os.environ['REDIS_HOST']
    REDIS_PORT = os.environ['REDIS_PORT']
    redis = await create_redis_pool((REDIS_HOST, REDIS_PORT), encoding='utf-8')


async def close_resources() -> None:
    '''
    Release resources
    '''
    redis.close()
    await redis.wait_closed()


def create_app() -> Application:
    app = Application([
        ("/hello", hello.HelloHandler),
    ])

    return app


if __name__ == '__main__':

    app = create_app()
    http_server = HTTPServer(app)
    http_server.listen(8000)
    IOLoop.current().start()

重要的是,我也可以在测试期间使用启动和关闭功能。

有什么想法吗?

tornado python-asyncio startup shutdown asgi
1个回答
0
投票

要创建池,请使用run_sync调用协程之前开始循环:

if __name__ == '__main__':
    IOLoop.current().run_sync(start_resources)
    ...

要在程序存在之前销毁池,请使用try...finally块,以便也考虑由于未处理的异常而导致的突然退出:

if __name__ == '__main__': 
    # create db pool
    IOLoop.current().run_sync(start_resources)

    ...

    try:
        # start the loop
        IOLoop.current().start()
    except:
        pass
    finally:
        # this will close the pool before exiting
        IOLoop.current().run_sync(close_resources)
© www.soinside.com 2019 - 2024. All rights reserved.