我有一个消息总线,并且一个类为消息总线订阅了许多方法,例如:
class BookingService(object):
def start(self):
self.msg_bus.login(self.user, self.password)
self.msg_bus.subscribe('/broadcast/aliveResponse', self.handleAliveResponse)
self.msg_bus.subscribe('/broadcast/musicInfoUpdated', self.handleMusicInfo)
self.msg_bus.subscribe('/broadcast/radioOnline', self.handleRadioOnline)
self.msg_bus.subscribe('/broadcast/radioOffline', self.handleRadioOffline)
self.msg_bus.subscribe('/broadcast/online', self.handleBroadcastOnline)
self.msg_bus.subscribe('/proxy/aliveResponse', self.handleEvent)
self.msg_bus.subscribe('/proxy/online', self.handleProxyOnline)
self.msg_bus.subscribe('/proxy/radioReady', self.handleEvent)
self.msg_bus.subscribe('/proxy/radioUpdate', self.handleEvent)
self.msg_bus.subscribe('/proxy/radioClosed', self.handleEvent)
self.msg_bus.subscribe('/message_bus/detached', self.handleDetached)
self.msg_bus.run()
它有效,但很难理解每个方法的消息路径是什么,我想要的是使用装饰器用方法订阅消息总线,它看起来像这样
class BookingService(object):
@subscribe('/broadcast/aliveResponse')
@subscribe('/broadcast/onLine')
def handleEvent(self, dest, data):
print dest, data
@subscribe('/proxy/aliveResponse')
def handleAnotherEvent(self, dest, data):
print dest, data
但是这里有一些难以解决的问题,首先,msg_bus属性属于实例,即属于self。我无法在类级别获得self.msg_bus。要解决这个问题,我可以这样写:
class BookingService(object):
subscribations = []
def subscribe(dest):
"""Decorator for subscribing function to destination
"""
def callee(func):
subscribations.append((dest, func))
return func
return callee
def subscribe_all(self):
for dest, func in self.subscribations:
self.msg_bus.subscribe(dest, func)
@subscribe('/broadcast/aliveResponse')
def handleEvent(self, dest, data):
print dest, data
def start(self):
self.subscribe_all()
我尝试将订阅收集到BookingService.subscribations中,然后在subscribe_all中将它们添加到msg_bus,但问题就出现了。我收到了一个错误
subscribations.append((dest, func))
NameError: global name 'subscribations' is not defined
似乎订阅不在订阅功能范围内,如何解决这个问题?
答案 0 :(得分:1)
不是将其放入实例的列表中,而是将其放入函数或类的列表中。
class BookingService(object):
def subscribe(dest):
"""Decorator for subscribing function to destination
"""
def callee(func):
if not hasattr(func, 'subscriptions'):
func.subscriptions = []
func.subscriptions.append((dest, func))
return func
return callee
def subscribe_all(self):
for classmember in dir(self):
for dest, func in getattr(getattr(self, classmember), 'subscriptions', []):
self.msg_bus.subscribe(dest, func)
@subscribe('/broadcast/aliveResponse')
def handleEvent(self, dest, data):
print dest, data
def start(self):
self.subscribe_all()
但是,您可能仍然遇到不受约束的方法的问题;注意“自我”的含义。
你可能还想在课程定义之外移动“subscribe”,或者将其重命名为“_subscribe”或使其成为self.subscribe()
的调用(目前self.subscribe()
将起作用但不是如何你期待)
答案 1 :(得分:0)
您可以在类主体中定义订阅,这使其成为类属性。 但是,当您使用它时,您将其用作全局。你必须从方法中得到它, 但是因为这是在创建课程之前发生的,所以你不能。
您可以将其设置为函数的属性,也可以使用包含函数和目标之间映射的全局字典。在这两种情况下,您都必须在subscribe_all方法中查看类中的所有函数,以查看它们是否有订阅。