title: Change PubSub subscription with redis-py
body: <p>I have a real-time webapp where a client receives updates from multiple Redis PubSub channels, built with gevent-socketio and redis-py. </p>
  
  <p>I'm looking at the <a href="https://github.com/sontek/django-tictactoe/blob/master/tictactoe/apps/core/views.py#L26" rel="nofollow">views.py, l.26</a> in the <a href="https://github.com/sontek/django-tictactoe" rel="nofollow">django-tictactoe</a> example. 
  It spawns a new greenlet when the client sends a subscribe message for a channel. The greenlet then subscribes to the Redis PubSub channel and blocks until a message is received.</p>
  
  <pre><code>class GameNamespace(BaseNamespace):
      def listener(self, chan):
              red = redis.StrictRedis(REDIS_HOST)
              red = red.pubsub()
              red.subscribe(chan)
  
              print 'subscribed on chan ', chan
  
              while True:
                  for i in red.listen():
                      self.send({'message': i}, json=True)
  
      def recv_message(self, message):
          action, pk = message.split(':')
  
          if action == 'subscribe':
              Greenlet.spawn(self.listener, pk)
  </code></pre>
  
  <p>From my understanding, it is not possible to add subscriptions without spawning new Greenlets or unsubscribe from subscriptions.</p>
  
  <p>How would you handle frequent subscriptions and unsubscriptions in an efficient way?</p>
  
  <p><strong>Update:</strong> What I'm building is a HTML5 realtime MMO game on a theoretically infinite 2D-map. Due to the size of the map, it is impossible to send the state of the whole map to the browser. The map is therefor partitioned in tiles which are loaded dynamically as the player drags the map (think Google Maps).</p>
  
  <p>Whenever the maps is dragged, the client/browser subscribes to updates for the tiles which just became visible and, after a short delay, unsubscribes from updates on tiles that became invisible. Changes to subscription should happen maybe once per second per player, so <em>frequent</em> is relative.</p>
  
  <p>The number of clients will (hopefully) be large. Theoretically, all players could look at the same part of the map, making <a href="http://redis.io/commands/subscribe" rel="nofollow">SUBSCRIBE</a> and <a href="http://redis.io/commands/unsubscribe" rel="nofollow">UNSUBSCRIBE</a> very expensive, as they are "<code>O(N) where N is the number of clients already subscribed to a channel</code>". In practice, it will be evenly spread over the world, so this should not be a problem.</p>
  
  <p>However, <strong>my main issue is that the Python Redis PubSub implementation blocks on listen.</strong> Once I call red.listen() in the example above, I can't change the subscription anymore until a message arrives. The example code above starts a new Greenlet with a new connection to Redis per subscription, which is probably a bad idea.</p>