Getting values with the right type in Redis
我在python应用程序中使用redis来存储诸如计数器和时间戳列表之类的简单值,但是尝试获取一个计数器并将其与数字进行比较时遇到了问题。
如果我做:
1 2 3 4 | import redis ... myserver = redis.Redis("localhost") myserver.set('counter', 5) |
然后尝试像这样获得该值:
1 2 | if myserver.get('counter') < 10: myserver.incr('counter') |
然后在if语句中遇到类型错误,因为我正在比较'5'<10,这意味着我正在存储一个整数值并获取一个字符串(可以认为是另一个值)。
我的问题是:这应该像那样工作吗? 我的意思是它是一个非常基本的类型,我知道是否必须解析对象但可以解析一个int? 看来我做错了。
我缺少任何配置吗?
有什么方法可以使redis返回正确的类型,而不总是返回字符串吗?
我之所以这样说是因为列表和日期时间甚至浮点值都相同。
我使用的redis-py客户端会出现问题,而不是redis本身吗?
从技术上讲,您需要自己进行维护。
但是,请看一下此链接,尤其是他们的README部分中的引用解析器和响应回调的部分,也许您可??以使用它。问题是这是否对您来说是一个过度的杀伤力。
正如@favoretti所说,响应回调将达到目的。它一点也不复杂,只需一行就可以了。
1 2 3 4 5 | 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 |
对于
1 2 3 4 | 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] |
与
看起来这就是redis存储数据的方式:
1 2 3 4 5 6 7 8 | 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 |
如果确实愿意,您可能会猴子修补
尽管利用
1 2 3 4 5 6 7 8 9 10 11 | # 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]} |
这是一个简单的客户端,它将减少上述示例中的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | """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() |
用法:
1 2 3 4 5 6 | >>> 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]} |
您可以将True设置为True
1 | redis.StrictRedis(host="localhost", port=6379, db=0, decode_responses=True) |
这是我的测试。两个redis连接:一个返回int类型,另一个返回float
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import redis age_field = redis.Redis() age_field.set_response_callback('HGET', int) age_field.hget('foo', 'age') # OUT: 40 a =age_field.hget('foo', 'age') type(a) # OUT: <type 'int'> gpa_field = redis.Redis() gpa_field.set_response_callback('HGET', float) gpa_field.hget('foo', 'gpa') # OUT: 2.5 b = gpa_field.hget('foo', 'gpa') type(b) # OUT: <type 'float'> |