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