【问题标题】:Redis blpop sometimes return tuple, sometime not?Redis blpop 有时会返回元组,有时不会?
【发布时间】:2016-09-24 12:14:27
【问题描述】:

我使用以下代码在我的 Redis 队列中放置/检索项目,但有时在解码 json 转储时会出错,因为返回的项目不是元组而是完整的 json。

这是课程:

class RedisQueue(object):
    """Simple Queue with Redis Backend"""
    def __init__(self, namespace, redis_url='redis://127.0.0.1:6379'):
        self.__db = redis.from_url(redis_url)
        self.redis_url = redis_url
        self.namespace = namespace

    def put(self, queue, item):
        """Put item into the queue."""
        self.__db.rpush('{0}:{1}'.format(self.namespace, queue), json.dumps(item))

    def get(self, queue, block=True, timeout=None):
        """Remove and return an item from the queue.

        If optional args block is true and timeout is None (the default), block
        if necessary until an item is available."""
        key = '{0}:{1}'.format(self.namespace, queue)
        if block:
            item = self.__db.blpop(key, timeout=timeout)
        else:
            item = self.__db.lpop(key)

        if item is not None:
            try:
                item = json.loads(item[1])
            except ValueError as e:
                sys.stderr.write("[ERROR JSON (in queue)] - {1} => {0}\n".format(str(e), str(item)))
                return None

        return item

我有时会在以下位置遇到异常:

    if item is not None:
        try:
            item = json.loads(item[1])
        except ValueError as e:
            sys.stderr.write("[ERROR JSON (in queue)] - {1} => {0}\n".format(str(e), str(item)))
            return None

也就是说:

[ERROR JSON (in queue)] - {"ip": null, "domain": "somedomain.com", "name": "Some user name", "contact_id": 12345, "signature": 
"6f496a4eaba2c1ea4e371ea2c4951ad92f41ddf45ff4949ffa761b0648a22e38"} => end is out of bounds

这是因为 item 是完整的 json,所以 json.loads(item[₁]) 会导致错误。但它只是偶尔发生,而不是每次都发生。当我手动检查 item 的值时,我有一个元组,其中键为 0,值(json 字符串)为 1,这是预期的。

为什么redis有时会返回item中的值,有时返回带有key,value的元组?

【问题讨论】:

  • lpop 总是只返回值。
  • ahahahhaaah ...但是..认真的吗?!为什么有区别?!
  • 哦,如果你愿意,请解释差异作为答案,我会接受它:)

标签: python json redis


【解决方案1】:

因为你发出了两个不同的命令,每个命令返回不同的东西。

LPOP 返回弹出的项目。它只需要一个键。 BLPOP 但是可以针对多个列表运行。因此,它返回从列表中弹出项目的数组,并弹出项目。但是,如果超时到期,并且没有可用的项目,它会返回一个 nil 批量数组。

在上面的链接中很容易获得关于此的文档。我强烈建议您查看 Redis 文档以了解您使用的命令,以确保您了解相似但不同的命令之间的差异。

在您的代码中,您将调用上述命令之一,但并不总是相同的。所以有时你会得到一个元组,而其他人会得到一个字符串。当你阻塞时:元组。当你不这样做时:字符串。

为了保持返回值类型的一致性,我总是调用BLPOP,而不是布尔值,使用用户指定的超时时间,或者在不想阻塞的情况下,阻塞超时时间为0。然后你总是会得到一个元组,尽管你必须抓住IndexError,当你试图访问一个空元组的第二个元素时你会得到。一个标准的 try/except 子句应该这样做。

【讨论】:

    猜你喜欢
    • 2019-08-22
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多