Mensajes entre instancias.

Pepe Aracil pepe en diselpro.com
Mie Mar 15 11:12:54 CET 2006


Aqui teneis una nueva versión de la clase Broadcast que permite tener listeners 
en modo "promiscuo", muy util para depurar el trasiego de mensajes. Tambien he 
añadido la capacidad a los listeners de devolver parámetros.

La proxima mejora será la retransmisión de mensajes a instancias remotas 
mediante XMLRPC. Esto ya supera mis necesidades actuales, pero lo hago por el 
puro placer de programar en Python ;-D

Por cierto Chema, en la implementación en que los eventos son objetos, Si yo 
creo un listener dentro del constructor de una clase y este listener tiene que 
registrarse en 10 eventos, ¿Tendrias que pasar estos 10 eventos como parámetros 
del constructor? ¿Serian todas la instancias de eventos variables publicas?


Saludos.


#! /usr/bin/python
import weakref

class Broadcast:
     def __init__(self):
         self.messages={}

     def __purge(self):
         for msg in self.messages:
             self.messages[msg] = [l for l in self.messages[msg] if l() <> None]
             if len(self.messages[msg]) == 0:
                 del(self.messages[msg])

     def register(self,owner,messages):
         self.__purge()
         wr_owner = weakref.ref(owner)
         if not isinstance(messages,(list,tuple)):
             messages = (messages,)

         for msg in messages:
             if not (msg in self.messages):
                 self.messages[msg] = []
             if not (wr_owner in self.messages[msg]):
                 self.messages[msg].append(wr_owner)

     def unregister(self,owner,messages):
         wr_owner = weakref.ref(owner)
         if not isinstance(messages,(list,tuple)):
             messages = (messages,)

         for msg in messages:
             if not (msg in self.messages):
                 continue
             if (wr_owner in self.messages[msg]):
                 self.messages[msg].remove(wr_owner)

     def unregister_all(self,owner):
         all_messages = self.messages.keys()
         self.unregister(owner,all_messages)

     def broadcast(self,sender,message,*params):
         results=[]
         # Enviamos mensaje a los listeners "promiscuos"
         if "_promisc_" in self.messages:
             for lst in self.messages["_promisc_"]:
                 ref=lst()
                 if ref:
                     ref.broadcast_cb(sender,message,*params)

         # Enviamos mensaje a los listeners subscritos
         if message in self.messages:
             for lst in self.messages[message]:
                 ref=lst()
                 if ref:
                     res = ref.broadcast_cb(sender,message,*params)
                     if res <> None:
                         results.append(res)
         if len(results) > 0:
             return results


if __name__=="__main__":

     class WindowA:
         def __init__(self,broadcast):
             self.broadcast = broadcast
             self.broadcast.register(self,("Mensaje1","Mensaje2"))

         def broadcast_cb(self,sender,message,*params):
             print "Recibido desde %s" % self
             print "Enviado por %s" % sender
             print "Mensaje %s" % message
             print "Paramatros extra %s" % (params,)
             return "Retorno WindowA"

     class WindowB:
         def __init__(self,broadcast):
             self.broadcast = broadcast
             self.broadcast.register(self,("Mensaje1"))

         def broadcast_cb(self,sender,message,*params):
             print "Recibido desde %s" % self
             print "Enviado por %s" % sender
             print "Mensaje %s" % message
             print "Paramatros extra %s" % (params,)
             return "Retorno WindowB"


     broadcast = Broadcast()
     wina=WindowA(broadcast)
     winb=WindowB(broadcast)

     ret = broadcast.broadcast(None,"Mensaje1",1,2,3)
     print "Retorno: %s" %(ret,)
     ret = broadcast.broadcast(None,"Mensaje2",3,4,5)
     print "Retorno: %s" %(ret,)
     print

     broadcast.unregister(wina,"Mensaje2")
     print "wina se ha desregistrado de Mensaje2"
     ret = broadcast.broadcast(None,"Mensaje1",1,2,3)
     print "Retorno: %s" %(ret,)
     ret = broadcast.broadcast(None,"Mensaje2",3,4,5)
     print "Retorno: %s" %(ret,)
     print

     del(winb)
     print "winb eliminada"
     ret = broadcast.broadcast(None,"Mensaje1",1,2,3)
     print "Retorno: %s" %(ret,)
     ret = broadcast.broadcast(None,"Mensaje2",3,4,5)
     print "Retorno: %s" %(ret,)
     print




Más información sobre la lista de distribución Python-es