Redis blpop有时会返回元组,有时候不会?

时间:2016-05-26 13:05:32

标签: python json redis

我使用以下代码在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的元组?

1 个答案:

答案 0 :(得分:2)

因为您发出了两个不同的命令,并且每个命令都返回不同的命令。

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

上述链接中提供了有关此文档的文档。我强烈建议您查看Redis文档以了解您使用的命令,以确保您了解相似但不同命令之间的差异。

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

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