首页 > 解决方案 > 模块“aioredis”没有属性“create_redis”

问题描述

使用 python 3.6.12 和 aioredis 2.0.0,asyncio 3.4.3

尝试使用 aioredis 中的代码段来测试 pub/sub:

import asyncio
import aioredis


async def reader(ch):
    while (await ch.wait_message()):
        msg = await ch.get_json()
        print("Got Message:", msg)


async def main():
    pub = await aioredis.create_redis(
        'redis://:password@localhost:6379')
    sub = await aioredis.create_redis(
        'redis://:password@localhost:6379')
    res = await sub.subscribe('chan:1')
    ch1 = res[0]

    tsk = asyncio.ensure_future(reader(ch1))

    res = await pub.publish_json('chan:1', ["Hello", "world"])
    assert res == 1

    await sub.unsubscribe('chan:1')
    await tsk
    sub.close()
    pub.close()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())

但以下错误不断弹出。

Traceback (most recent call last):
  File "tests/test_async_redis.py", line 32, in <module>
    result = loop.run_until_complete(main())
  File "/Users/dustinlee/.pyenv/versions/3.6.12/lib/python3.6/asyncio/base_events.py", line 488, in run_until_complete
    return future.result()
  File "tests/test_async_redis.py", line 12, in main
    pub = await aioredis.create_redis(
AttributeError: module 'aioredis' has no attribute 'create_redis'

谁能告诉我我做错了什么?可能是显而易见的,但我只是没有看到。谢谢!

标签: pythonaioredis

解决方案


aioredis从2.0版开始,现在遵循库的公共 API 实现redis-py

aioredis文档页面

aioredis v2.0 现在是 redis-py 的完全兼容的异步原生实现。整个核心和公共 API 已被重新编写,以尽可能地遵循 redis-py 的实现。

所以该方法aioredis.create_redis在 2.0 版本中不再是您可以用来建立连接的公共 API。create_redis如果您希望该方法起作用,请使用小于 2 的版本。

您可以参考新的pub sub 示例

此处复制的代码以防链接将来不起作用。

import asyncio
import async_timeout
import aioredis

STOPWORD = "STOP"


async def pubsub():
    redis = aioredis.Redis.from_url(
        "redis://localhost", max_connections=10, decode_responses=True
    )
    psub = redis.pubsub()

    async def reader(channel: aioredis.client.PubSub):
        while True:
            try:
                async with async_timeout.timeout(1):
                    message = await channel.get_message(ignore_subscribe_messages=True)
                    if message is not None:
                        print(f"(Reader) Message Received: {message}")
                        if message["data"] == STOPWORD:
                            print("(Reader) STOP")
                            break
                    await asyncio.sleep(0.01)
            except asyncio.TimeoutError:
                pass

    async with psub as p:
        await p.subscribe("channel:1")
        await reader(p)  # wait for reader to complete
        await p.unsubscribe("channel:1")

    # closing all open connections
    await psub.close()


async def main():
    tsk = asyncio.create_task(pubsub())

    async def publish():
        pub = aioredis.Redis.from_url("redis://localhost", decode_responses=True)
        while not tsk.done():
            # wait for clients to subscribe
            while True:
                subs = dict(await pub.pubsub_numsub("channel:1"))
                if subs["channel:1"] == 1:
                    break
                await asyncio.sleep(0)
            # publish some messages
            for msg in ["one", "two", "three"]:
                print(f"(Publisher) Publishing Message: {msg}")
                await pub.publish("channel:1", msg)
            # send stop word
            await pub.publish("channel:1", STOPWORD)
        await pub.close()

    await publish()


if __name__ == "__main__":
    import os

    if "redis_version:2.6" not in os.environ.get("REDIS_VERSION", ""):
        asyncio.run(main())

您也可以参考redis-py文档,因为它应该是aioredis2.0 现在紧跟的内容。


推荐阅读