Heroku で Redis の値を適切に扱う

Python で Redis を使用する際に、値をセットしてそれを取得するのは端的に書くとこんな感じになるでしょう。

>>> from redis import Redis
>>>
>>> c = Redis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB)
>>> c.set('foo', 'bar') # 'foo' をキー、 'bar' を値として保存
>>> v = c.get('foo')

しかし、これだといざ v を使おうとすると単なる文字列ではなくてギャフンとなったりします。実際にプリントしてみるとわかりますが、取り出した値はバイトオブジェクトになります。

>>> print(v)
b'bar'

こうならないように、 Redis クライアントのオブジェクトを作成する際に charset と decode_responses の設定をしておくと取り出した値が文字列となります。

>>> c = Redis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB
...           charset='utf-8', decode_responses=True)
>>> v = c.get('foo')
>>> print(v)
'bar'

一方で、 Heroku を使っていて Heroku Resis アドオンを使うようにしていると REDIS_URL という環境変数がセットされ、その値は redis://h:solongstring@ec2-instance.amazonaws.com:PORT のようになります。こちらを使う際にはいちいちパースしてやる必要はなくて、  redis パッケージの from_url() を使ってやれば良いです。

>>> from os import environ
>>> from redis import from_url
>>> c = from_url(environ.get('REDIS_URL')
>>> c.set('foo', 'bar')
>>> v = c.get('foo')

ただ、これだと先ほどと同じく取得した値はバイトオブジェクトになってしまいます。ということで、 from_url() で Redis クライアントを作るときにも先ほどと同様のパラメータを使うことで、文字列にデコードされるようになります。

>>> c = from_url(environ.get('REDIS_URL',
...              charset='utf-8', decode_responses=True)
>>> v = c.get('foo')
>>> print(v)
'bar'

めでたしめでたし。ちなみに僕は Heroku で Redis から取り出した値を JSON にしようとしていてエラーが起こって気がついたのでした。

この記事が気に入ったらサポートをしてみませんか?