通过等待Python中的协程来设置类属性

问题描述

我有一个类,该类的属性包含一个Redis连接,如下所示:

import redis

class RedisService:
    db = redis.Redis(host=RedisConfig.REdis_HOST,port=RedisConfig.REdis_PORT)

    @staticmethod
    def exists(key):
        return RedisService.db.exists(key)

这很好。但是现在我想用异步替代品代替它:

import aioredis

class RedisService:
    db = await aioredis.create_connection((RedisConfig.REdis_HOST,RedisConfig.REdis_PORT))

    @staticmethod
    async def exists(key):
        value = await RedisService.db.execute('GET',key)
        return value

但是不允许await为类属性分配值。如果删除等待,当我致电RedisService.exists()时,我得到:

File "./src/service/redis.py",line 12,in exists
     value = await RedisService.db.execute('GET',key)
 AttributeError: 'coroutine' object has no attribute 'execute'

那么如何通过等待协程为类属性分配值?

请注意,我直接调用await RedisService.exists()而不创建对象实例。它应该是一个静态方法,并且由于某些BL原因,应该在不创建实例的情况下调用它。

解决方法

您可以在模块中创建一个init函数,以初始化所需的类属性:

# let's assume module name redis_service.py

class RedisService:
    ...

async def init():
    RedisService.db = await aioredis.create_connection(...)

您将从main入口点调用此函数:

import redis_service
...

async def main():
    await redis_service.init()
    ...

if __name__ == '__main__':
    asyncio.run(main())

这样做的好处是,如果您多次运行asyncio.run(),则可以重新初始化“全局”异步数据。另外,aioredis.create_connection()返回的对象很可能与当前事件循环相关,因此在类定义时执行该对象将排除使用asyncio.run开头。