在Redis中获取具有正确类型的值

jer*_*uki 26 python types type-conversion redis

我在我的python应用程序中使用redis来存储简单的值,如计数器和时间戳列表,但是试图获得一个计数器并将其与数字进行比较我遇到了一个问题.

如果我做:

import redis
...
myserver = redis.Redis("localhost")
myserver.set('counter', 5)
Run Code Online (Sandbox Code Playgroud)

然后尝试获得这样的值:

if myserver.get('counter') < 10:
     myserver.incr('counter')
Run Code Online (Sandbox Code Playgroud)

然后我在if语句中得到一个类型错误,因为我正在比较'5'<10,这意味着我存储一个整数值并获得一个字符串(可以认为是一个不同的值).

我的问题是:这应该是那样的吗?我的意思是它是一个非常基本的类型,我理解我是否必须解析对象而不是int?似乎我做错了什么.

有什么配置我不见了?

有没有办法让redis返回正确的类型而不总是一个字符串?我这样说是因为它对于列表和日期时间甚至是浮点值都是一样的.

这可能是我正在使用的redis-py客户端的问题,而不是redis本身?

fav*_*tti 15

从技术上讲,你需要自己解决这个问题.

但是,请看一下这个链接,特别是在他们的自述文件中引用解析器和响应回调的部分,也许这是你可以使用的东西.问题是这对你来说是否有点矫枉过正.


pin*_*ngz 14

正如@favoretti所说,响应回调将成功.它根本不复杂,只有一条线,所有都将被处理.

In [2]: import redis
In [3]: r = redis.Redis()
In [10]: r.set_response_callback('HGET', float)
In [11]: r.hget('myhash', 'field0')
Out[11]: 4.6
Run Code Online (Sandbox Code Playgroud)

for hmget,它返回一个字符串列表,而不是一个字符串,所以你需要构建一个更全面的回调函数:

In [12]: r.set_response_callback('HMGET', lambda l: [float(i) for i in l])

In [13]: r.hmget('myhash', 'field0')
Out[13]: [4.6]
Run Code Online (Sandbox Code Playgroud)

同样的hgetall.

  • 试图为"HMGET"和"HGETALL"设置浮动回调,但遗憾的是它失败了.我想它试图转换哈希键名称. (2认同)

小智 6

您可以将 decode_respone 设置为 True

redis.StrictRedis(host="localhost", port=6379, db=0, decode_responses=True)
Run Code Online (Sandbox Code Playgroud)

  • 似乎不起作用 &gt;&gt;&gt; r= redis.StrictRedis(decode_responses=True) &gt;&gt;&gt; r.set('world', 123) True &gt;&gt;&gt; r.get('world') '123' (3认同)

res*_*ate 6

虽然利用set_response_callback对于简单数据类型来说很好,但如果您想知道存储字典、列表、元组等内容的最快和最简单的方法——并保留它们可能包含或可能不包含的 Python 原生数据类型——我推荐使用python的内置pickle库:

# Imports and simplified client setup
>>> import pickle
>>> import redis
>>> client = redis.Redis()
# Store a dictionary
>>> to_store = {'a': 1, 'b': 'A string!', 'c': [1, True, False, 14.4]}
>>> client.set('TestKey', pickle.dumps(to_store))
True
# Retrieve the dictionary you just stored.
>>> retrieved = pickle.loads(client.get('TestKey'))
{'a': 1, 'b': 'A string!', 'c': [1, True, False, 14.4]}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的客户端,它将减少pickle上面示例中的样板,并为您提供一个干净的界面,用于在 Redis 中存储和检索本机 Python 数据类型:

"""Redis cache."""
import pickle
import redis

redis_host = redis.Redis()


class PythonNativeRedisClient(object):
    """A simple redis client for storing and retrieving native python datatypes."""

    def __init__(self, redis_host=redis_host):
        """Initialize client."""
        self.client = redis_host

    def set(self, key, value, **kwargs):
        """Store a value in Redis."""
        return self.client.set(key, pickle.dumps(value), **kwargs)

    def get(self, key):
        """Retrieve a value from Redis."""
        val = self.client.get(key)
        if val:
            return pickle.loads(val)
        return None

redis_client = PythonNativeRedisClient()
Run Code Online (Sandbox Code Playgroud)

用法:

>>> from some_module import redis_client
>>> to_store = {'a': 1, 'b': 'A string!', 'c': [1, True, False, 14.4]}
>>> redis_client.set('TestKey', to_store)
True
>>> retrieve = redis_client.get('TestKey')
{'a': 1, 'b': 'A string!', 'c': [1, True, False, 14.4]}
Run Code Online (Sandbox Code Playgroud)


Joe*_*ett 5

看起来这就是redis存储数据的方式:

redis 127.0.0.1:6379> set counter 5
OK
redis 127.0.0.1:6379> type counter
string
redis 127.0.0.1:6379> incr counter
(integer) 6
redis 127.0.0.1:6379> type counter
string
Run Code Online (Sandbox Code Playgroud)

如果确实愿意,您可能会猴子修补redis-py客户端以推断数据类型。