web-dev-qa-db-ja.com

Redisで適切なタイプの値を取得する

pythonアプリケーションでredisを使用して、カウンターやタイムスタンプリストなどの単純な値を保存していますが、カウンターを取得し、それを数値と比較しようとして問題が発生しました。

私が行った場合:

import redis
...
myserver = redis.Redis("localhost")
myserver.set('counter', 5)

そして、次のようにその値を取得しようとします:

if myserver.get('counter') < 10:
     myserver.incr('counter')

次に、 '5' <10を比較しているため、ifステートメントで型エラーが発生します。つまり、(整数値を格納して文字列1を取得している(これは別の値と見なすことができます)値)。

私の質問は、これはそのように機能するはずですか?私はそれが非常に基本的なタイプであることを意味します、私はオブジェクトを解析する必要があるかどうか理解しますが、int?私は何か間違っているようです。

不足している構成はありますか?

Redisが常に文字列ではなく正しいタイプを返すようにする方法はありますか?これは、リストと日時、または浮動小数点値でも同じであるためです。

これは私が使用しているredis-pyクライアントの問題であり、redis自体の問題ではないでしょうか?

26
jeruki

技術的に言えば、自分でそれを処理する必要があります。

ただし、 このリンク を見てください。特に、パーサーと応答コールバックを参照するREADMEの部分で、多分それはあなたが使用できるものです。質問です。これはあなたにとってやりすぎかどうか。

15
favoretti

@favorettiが言ったように、応答のコールバックでうまくいきます。まったく複雑ではなく、1行だけですべてが処理されます。

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

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]

hgetallも同様です。

14
pingz

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

本当にしたい場合は、redis-pyクライアントにモンキーパッチを適用してデータ型を推測することができます。

5
Joel Cornett

Trueのようにdecode_responeを設定できます

redis.StrictRedis(Host="localhost", port=6379, db=0, decode_responses=True)
3
Lucas Picoloto

set_response_callbackは、単純なデータ型には問題ありませんが、辞書、リスト、タプルなどを格納するための最速かつ最も簡単なルートについて疑問に思っている場合、およびそれらに含まれる、または含まれていない可能性があるpythonネイティブのデータ型を保持する場合– I 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]}

上記の例で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()

使用法:

>>> 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]}
2
respondcreate

これが私のテストです。 2つのredis接続:1つはint型を返し、もう1つはfloat

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'>
0
Jie Bao