I created a small class to perform basic operations with redis, using aioredis.
class RedisService: def __init__(self, r_url) -> str: self.redis = r_url async def create_connection(self): return await aioredis.create_redis(self.redis) async def _get(self, key) -> str: try: return await self.create_connection().get(key, encoding='utf-8') finally: await self._close() async def _set(self, key, value) -> None: await self.create_connection().set(key, value) await self._close() async def _close(self) -> None: self.create_connection().close() await self._redis.wait_closed()
And a test handler to call the write/read operation for redis
@router.post('/perform') async def index(): key = 'test' value = 'test' value = await RedisService(r_url)._set(key, value) return {'result': value}
But get error
await self.create_connection.set(key, value) AttributeError: ''coroutine'' object has no attribute 'set'
I guess the problem could be that the asynchronous code has to be run through an event loop
asyncio.run(some coroutine)
But I can’t understand how I can build this logic into my code
Advertisement
Answer
Your problem is how you use create_connection
. You have to call it and await what it returns.
await self.create_connection()
You’ll then need to await set
and get
as well. As a one-liner this would get messy.
await (await self.create_connection()).set(key, value)
To help clean this up, you should split the awaits into separate statements.
conn = await self.create_connection() await conn.set(key, value)
Creating a new connection each time you need to perform an operation can be expensive. I’d recommend changing create_connection
in one or two ways.
Either have it attach the connection to your instance
async def create_connection(self): self.conn = await aioredis.create_redis(self.redis)
You can call this after you instantiate an instance of RedisService
and then use
await self.conn.set(key, value)
Or you can switch to using a connection pool.
async def create_connection(self): return await aioredis.create_redis_pool(self.redis)