Publish/subscribe
Publish/Subscribe
Redis-py includes a PubSub object, subscribes to channels, and listens for new messages. Creating a PubSub object is easy.
/redis-py with PUBSUB goals that can subscribe to channels and listen to new information. Here's how to create a pubsub:
>>> r = Redis. Strictredis (...)
>>> p = r.pubsub ()
Once a PubSub instance is created, channels and patterns can being subscribed to.
After creating the PubSub instance, you can listen to channels and modes.
>>> p.subscribe (' My-first-channel ', ' My-second-channel ', ...)
>>> p.psubscribe (' my-* ', ...)
The PubSub instance is now subscribed to those channels/patterns. The subscription confirmations can be seen by reading messages from the PubSub instance.
Now this pubsub strength has subscribed to these channels/modes. By reading the information from the PubSub instance, you can determine that the subscription has succeeded.
>>> 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}
Every message read from a PubSub instance is a dictionary with the following keys.
All information read through the PubSub instance is a dictionary with the following keys:
Type:one of the following: ' Subscribe ', ' unsubscribe ', ' psubscribe ', ' Punsubscribe ', ' message ', ' pmessage '
Type: One of the following: ...
Channel:the Channel [un]subscribed to or the channel a message is published to
Channel: information is posted to subscribed or subscribed channels
Pattern:the Pattern that matched a published message ' s channel. 'll is None in the all cases except for ' pmessage ' types.
Mode: A pattern that corresponds to a channel that publishes information. Except the ' pmessage ' type is ' none '.
Data:the message data. With [Un]subscribe messages, this value would be the number of channels and patterns the connection are currently subscribed To. With [p]message messages, this value would be the actual published message.
Data: Data in the information. With subscription or non-subscription information, this key value represents the number of channels or modes that the connection is subscribed to. With [p]message information, this key value represents the actual published information.
Let's send a message now.
to send a message now.
# The Publish method returns the number matching channel and pattern
# subscriptions.
The published method returns the number of subscriptions for the corresponding channel and mode
' My-first-channel ' matches both the ' My-first-channel '
# Subscription and the ' my-* ' pattern Subscription, so this message would
# is delivered to 2 channels/patterns
' my-first-channel ' corresponding ' My-first-channel ' subscriptions and ' my-* ' mode subscriptions, so this information will be transmitted to two channels/modes >>> 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 '}
Unsubscribing works just like subscribing. If no arguments is passed to [P]unsubscribe, all channels or patterns'll is unsubscribed from.
Canceling subscriptions and subscriptions is the same thing. If no parameters are passed to [P]unsubscribe], all channels and modes will be unsubscribed.
>>> 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 also allows you-register callback functions to handle published messages. Message handlers take a single argument, the message, which are a dictionary just like the examples above. To subscribe to a channel or pattern with a message handler, pass the channel or pattern name as a keyword argument with I TS value being the callback function.
Redis-py can also allow you to group a callback function to process the published information. The information processor will accept a parameter, which is the same as the dictionary example mentioned above. When you want to subscribe to a channel or mode with the information processor, transfer the parameter with the name of the channel or mode as the key, and the value of the parameter is the callback function name.
When a message was read on a channel or pattern with a message handler, the message dictionary was created and passed to the Message handler. In this case, a None of value is returned from Get_message () since the message was already handled.
When the information is read by a channel or pattern processor, the dictionary of information is created and then transmitted to the information processor. In this case, no value is returned by Get_message () because the information has been processed by the processor.
>>> def my_handler (message):
.. print ' MY HANDLER: ', message[' data '
>>> p.subscribe (**{' My-channel ': My_handler})
# Read the Subscribe confirmation message
Read the subscription confirmation information
>>> P.get_message ()
{' Pattern ': None, ' type ': ' Subscribe ', ' Channel ': ' My-channel ', ' Data ': 1L}
>>> r.publish (' My-channel ', ' awesome data ')
1
# for the message handler to work, we need tell the instance to read data.
# This can is done with several ways (read more below). We ' ll just use
# The familiar Get_message () function for now
In order for the information processor to work, we have to let this instance read the data.
There are several ways to do this (more on this).
Here we use the familiar Get_message () function
>>> message = P.get_message ()
MY handler:awesome Data
# Note Here the My_handler callback printed the string above.
# ' message ' is None because the message were handled by our handler.
Notice here that the callback function my_handler the printed string
' Message ' is empty because the message was processed by our information processor >>> print message
None
If your application is isn't interested in the (sometimes noisy) subscribe/unsubscribe confirmation messages, can ignore them by passing ignore_subscribe_messages=true to R.pubsub (). This would cause all subscribe/unsubscribe messages to is read, but they won ' t bubble up to your application.
If your app doesn't need to subscribe/unsubscribe confirmation (sometimes noisy), you can ignore them: transfer ignore_subscribe_messages=true to R.pubsub (), which will make all subscription/unsubscribe information read, But they're not going to fill your app.
>>> p = r.pubsub (ignore_subscribe_messages=true)
>>> p.subscribe (' My-channel ')
>>> p.get_message () # Hides the subscribe message and returns None
>>> r.publish (' My-channel ')
1
>>> P.get_message ()
{' channel ': ' My-channel ', ' data ': ' My data ', ' pattern ': None, ' type ': ' Message '}
There is three different strategies for reading messages.
Here are a few ways to read information.
The
The examples above has been using pubsub.get_message (). Behind the scenes, Get_message () uses the system ' s ' select ' module to quickly poll the connection ' s socket. If there ' s data available to be read, get_message () would read it, format the message and return it or pass it to a message Handler. If There's no data to is read, Get_message () would immediately return None. This makes it trivial to integrate into an existing event loop inside your application.
The previous example uses Pubsub.get_message (), in fact, Get_message () uses the system's ' select ' module to quickly detect (poll) the connected socket. If there is data to read, Get_message () reads them, formats the information and then passes it on to the processor. If no data can be read, return none immediately. This approach is more straightforward to incorporate into your app's event loop.
>>> while True:
>>> message = P.get_message ()
>>> if message:
>>> # do Something with the message
>>> time.sleep (0.001) # is nice to the system:)
Older versions of Redis-py only read messages with Pubsub.listen (). Listen () are a generator that blocks until a MES Sage is available. If your application doesn ' t need to does anything else but receive and act on messages received from Redis, listen () are an E Asy-to-get up an running.
Older versions of REDIS-PY will only read information with Pubsub.listen (). Listen () is a transmitter that works only when information is present. Listen () is a relatively simple way to operate if the application does not need anything other than receiving and then processing information from Redis.
>>> for message in P.listen ():
... # do something with the message
The third option runs an event loop in a separate thread. Pubsub.run_in_thread () creates a new thread and starts th E event loop. The thread object is returned to the caller of Run_in_thread (). The caller can use the Thread.stop () method to shut down the event loop and thread. Behind The scenes, this is simply a wrapper around get_message () so runs in a separate thread, essentially creating a ti NY non-blocking event loop for you. Run_in_thread () takes an optional sleep_time argument. If specified, the event loop would call Time.sleep () with the value in each iteration of the loop.
The third method is to run an event loop on another thread. Pubsub.run_in_thread () Creates a new thread and then starts the event loop. This thread target is returned to the caller of Run_in_thread (). The caller can use the Thread.stop () method to stop the event loop and thread. In fact, this is a simple get_message () wrapper that runs on another thread, essentially creating a small, non-blocking event loop. Run_in_thread () can also accept a selective sleep_time parameter. If indicated, this event loop summons Time.sleep () and then gives the time of the break for Each loop.
Note:since we ' re running in a separate thread, there ' s no-to-handle messages that aren ' t automatically handled wit H registered message handlers. Therefore, redis-py prevents you from calling Run_in_thread () if you ' re subscribed to patterns or channels that don ' t has message handlers attached.
Note that because we are running on another thread, there is no way to process information that is not automatically processed by (the group's information processor). So redis-py does not allow you to summon Run_in_thread () if you subscribe to a mode or channel that does not have an information processor.
>>> p.subscribe (**{' My-channel ': My_handler})
>>> thread = P.run_in_thread (sleep_time= 0.001)
# The event loop is now running in the background processing messages
# when it's time to shut it down ...
Now this event loop is processing information in the background
when it needs to be closed ...
>>> thread.stop ()
A PubSub object adheres to the same encoding semantics as the client instance it is created from. Any channel or pattern that ' s Unicode would be encoded using the charset specified on the client before being sent to Redis . If the client ' s decode_responses flag is set the False (the default), the ' channel ', ' pattern ' and ' data ' values in MESSAG E dictionaries would be a byte strings (str on Python 2, bytes on Python 3). If the client ' s decode_responses is True, then the ' channel ', ' pattern ' and ' data ' values would be
automatically decoded To Unicode strings using the client ' s CharSet. The
one pubsub target follows the same encoding format as the customer instance. Before being sent to Redis, any Unicode channel or mode will be encoded as specified by the CharSet. If the customer's decode_responses flag is set to the default false, ' channel ', the value of the Information dictionary in ' pattern ' and ' data ' is a byte string. (Str on Python 2, bytes on Python 3).
If the client's client's decode_responses is true, it is automatically decoded to the customer's charset.
PubSub objects remember what channels and patterns they is subscribed to. In the event of a disconnection such as a network error or timeout, the PubSub object would re-subscribe to all prior Chann Els and patterns when reconnecting. Messages that were published while the client is disconnected cannot be delivered. When your ' re finished with a PubSub object, call its-close () method to shutdown the connection.
The PubSub target remembers the channel or mode he subscribed to. When a disconnection occurs because of a network failure or a pause, he subscribes to the previous mode and channel again before reconnecting. Information that is posted when the connection is broken is not delivered. When you are finished using the PubSub target, summon its. Close () method to close the connection.
>>> p = r.pubsub ()
>>> ...
>>> P.close ()
Reds pub/sub Official Document translation