python redis 模塊 官方文檔(中)

Publish / Subscribe

redis-py包含一個PubSub對象,來訂閱頻道和監聽消息,建立PubSub對象很簡單python

>>> r = redis.StrictRedis(...) 
>>> p = r.pubsub()
一旦一個PubSub對象被建立,頻道channel和匹配模式(基於正則表達式的channel)就可以訂閱了
>>> p.subscribe('my-first-channel', 'my-second-channel', ...) 
>>> p.psubscribe('my-*', ...)
如今PubSub對象能夠訂閱這些頻道了,能夠從PubSub對象讀取消息來確認是否訂閱成功
>>> p.get_message() 
{'pattern': None, 'type': 'subscribe', 'channel': 'my-second-channel', 'data': 1L} 
>>> p.get_message() 
{'pattern': None, 'type': 'subscribe', 'channel': 'my-first-channel', 'data': 2L}
 >>> p.get_message()
 {'pattern': None, 'type': 'psubscribe', 'channel': 'my-*', 'data': 3L}

從PubSub對象讀取的消息時一個包含一下鍵的字典
正則表達式

type:能夠是如下值中的一個redis

 ‘subscribe’, ‘unsubscribe’, ‘psubscribe’, ‘punsubscribe’, ‘message’, ‘pmessage’網絡

channel:訂閱或取消訂閱的頻道或者消息要發送的頻道socket

pattern: 匹配一個信息頻道的模式,除了'pmessage'其餘狀況下都是none測試

data:消息數據,對於(非)訂閱消息,這個值會是當前訂閱的channel和匹配模式鏈接的數量,對於[p]message,這個值就是發送的消息編碼

如今就能夠發送消息了spa

 發送方法返回channel匹配和模型pattern匹配的數量
# 'my-first-channel' 匹配 'my-first-channel' channel訂閱和'my-*' pattern訂閱
#因此這些消息會被傳送給2個channel或pattern
>>> r.publish('my-first-channel', 'some data')
 2 
>>> p.get_message()
 {'channel': 'my-first-channel', 'data': 'some data', 'pattern': None, 'type': 'message'} 
>>> p.get_message() 
{'channel': 'my-first-channel', 'data': 'some data', 'pattern': 'my-*', 'type': 'pmessage'}

對於取消訂閱,和訂閱同樣,若是沒有傳遞參數,會取消全部訂閱線程

>>> p.unsubscribe()
>>> p.punsubscribe('my-*')
>>> p.get_message()
{'channel': 'my-second-channel', 'data': 2L, 'pattern': None, 'type': 'unsubscribe'}
>>> p.get_message()
{'channel': 'my-first-channel', 'data': 1L, 'pattern': None, 'type': 'unsubscribe'}
>>> p.get_message()
{'channel': 'my-*', 'data': 0L, 'pattern': None, 'type': 'punsubscribe'}

redis-py 也容許你註冊一個回調功能來控制消息發佈.消息控制器只有一個參數,message,就像上面例子同樣是一個字典.用消息控制器訂閱頻道channel或者匹配樣式pattern,傳送channel或pattern做爲關鍵字參數,值做爲回調功能
code

當使用消息控制器從channel或pattern讀取消息時,消息字典被建立並傳遞給消息控制器.這種狀況下,因爲消息已經被處理,get_message()返回一個None值

>>> def my_handler(message):
...     print 'MY HANDLER: ', message['data']
>>> p.subscribe(**{'my-channel': my_handler})
# 讀取訂閱確認信息
>>> p.get_message()
{'pattern': None, 'type': 'subscribe', 'channel': 'my-channel', 'data': 1L}
>>> r.publish('my-channel', 'awesome data')
1
#因爲消息控制器的做用,咱們須要告訴實例讀取數據,能夠有多種方式處理,
#這裏咱們只使用get_message()
>>> message = p.get_message()
MY HANDLER:  awesome data
#注意這裏my_handler回調打印了上面的字符串 
# `message`是 None 由於消息被控制器控制了
>>> print message
None

若是你的應用不關心訂閱/取消訂閱確認消息(有時候是噪音),你能夠傳一個 ignore_subscribe_messages=True給 r.pubsub().這會引發全部的訂閱非訂閱消息讀取,但不會出如今你的應用中

>>> p = r.pubsub(ignore_subscribe_messages=True)
>>> p.subscribe('my-channel')
>>> p.get_message() 
 #隱藏了訂閱消息,返回None
 >>> r.publish('my-channel')
 1
 >>> p.get_message()
 {'channel': 'my-channel', data': 'my data', 'pattern': None, 'type': 'message'}

有三種不一樣的讀取消息的策略

上面的例子使用pubsub.get_message().在這種場景,get_message()使用系統的'select'模式快速測試鏈接的socket.若是有數據能夠被讀取,get_message()會讀取它,處理後返回或者傳遞給消息處理器.若是沒有數據讀取,get_message()會馬上返回None.這使得整合到你的應用中一個已存的事件循環並不重要

>>> while True:
>>>     message = p.get_message()
>>>     if message:
>>>        # do something with the message
>>>     time.sleep(0.001)  # be nice to the system :)

redis-py更老的版本只能用 pubsub.listen()讀取消息,listen()是一個生成器,會阻塞直到有消息能夠得到.若是你的應用不須要作任何事除了從redis接收消息,並對消息作出反應,listen()是一個簡單的運行方式

>>> for message in p.listen():...     # do something with the message

第三種選擇是在單獨的線程裏運行一個事件循環, pubsub.run_in_thread() 建立一個新的線程並啓動事件循環.線程對象被返回給調用者run_in_thread().調用者可使用 thread.stop() 來關閉事件循環和線程.在這種場景下,運行線程的只是一個簡單的對get_message()的包裝器,尤爲是你建立一個小的非阻塞的事件循環. run_in_thread() 有一個可選擇的 sleep_time參數.若是被指定,事件循環會在每次循環迭代時用指定的值調用time.sleep()

注意,因爲咱們運行了一個單獨的線程,沒有辦法控制不是由註冊的消息控制器自動控制的消息.所以,若是你正在訂閱沒有消息控制器關聯的pattern或channel,redis-p會阻止你調用 run_in_thread()

>>> p.subscribe(**{'my-channel': my_handler})
>>> thread = p.run_in_thread(sleep_time=0.001)
# 如今事件循環在後臺運行處理消息
# 當要關閉該線程時
>>> thread.stop()

一個PubSub對象綁定到一樣編碼的語義做爲它建立的客戶端實例.任何採用unicode的pattern和channel在發給Redis以前會被編碼爲指定的字符集.若是客戶端的解碼flag decode_responses被設定爲False(默認值),消息字典中的 ‘channel’, ‘pattern’ 和 ‘data’會變成byte字符串((Python 2時str,  Python 3時byte).若是客戶端decode_responses 是True,‘channel’, ‘pattern’ 和 ‘data’值會使用客戶端的字符集自動解碼爲unicode字符

PubSub對象保存了他們訂閱的channel和pattern.在沒法鏈接的事件中,如網絡錯誤或超時,當從新鏈接時PubSub對象會從新訂閱全部的先前的channel和pattern.沒法鏈接期間發佈的消息沒法再呈現.當你要結束一個PubSub對象時,調用close()方法關閉鏈接

>>> p = r.pubsub()
>>> ...
>>> p.close()

Redis官方文檔https://pypi.python.org/pypi/redis/

相關文章
相關標籤/搜索