2011-10-03 121 views
1

在扭曲的應用程序中,我有一系列通過Observable模式進行交互的資源控制器/管理器類。一般來說,大多數觀察者都會訂閱特定的頻道(例如「foo.bar.entity2」),但在某些情況下,我想知道特定頻道中的所有事件(例如「foo。*」)我寫了類似以下內容:支持多通道訂戶的Python可觀察實現

from collections import defaultdict 

    class SimplePubSub(object): 

     def __init__(self): 
      self.subjects = defaultdict(list) 


     def subscribe(self, subject, callbackstr): 
      """ 
       for brevity, callbackstr would be a valid Python function or bound method but here is just a string 
      """ 
      self.subjects[subject].append(callbackstr) 

     def fire(self, subject): 
      """ 
       Again for brevity, fire would have *args, **kwargs or some other additional message arguments but not here    
      """ 

      if subject in self.subjects: 
       print "Firing callback %s" % subject 
       for callback in self.subjects[subject]: 
        print "callback %s" % callback 



    pubSub = SimplePubSub() 
    pubSub.subscribe('foo.bar', "foo.bar1") 
    pubSub.subscribe('foo.foo', "foo.foo1") 

    pubSub.subscribe('foo.ich.tier1', "foo.ich.tier3_1") 
    pubSub.subscribe('foo.ich.tier2', "foo.ich.tier2_1") 
    pubSub.subscribe('foo.ich.tier3', "foo.ich.tier2_1") 

    #Find everything that starts with foo 
    #say foo.bar is fired 
    firedSubject = "foo.bar" 
    pubSub.fire(firedSubject) 
    #outputs 
    #>>Firing callback foo.bar 
    #>>callback foo.bar1 

    #but let's say I want to add a callback for everything undr foo.ich 

    class GlobalPubSub(SimplePubSub): 

     def __init__(self): 
      self.globals = defaultdict(list) 
      super(GlobalPubSub, self).__init__() 


     def subscribe(self, subject, callback): 
      if subject.find("*") > -1: 
       #assumes global suscriptions would be like subject.foo.* and we want to catch all subject.foo's 
       self.globals[subject[:-2]].append(callback) 
      else: 
       super(GlobalPubSub, self).subscribe(subject, callback) 

     def fire(self, subject): 
      super(GlobalPubSub, self).fire(subject) 
      if self.globals: 
       for key in self.globals.iterkeys(): 
        if subject.startswith(key): 
         for callback in self.globals[key]: 
          print "global callback says", callback 

    print "Now with global subscriptions" 
    print 
    pubSub = GlobalPubSub() 
    pubSub.subscribe('foo.bar', "foo.bar1") 
    pubSub.subscribe('foo.foo', "foo.foo1") 

    pubSub.subscribe('foo.ich.tier1', "foo.ich.tier3_1") 
    pubSub.subscribe('foo.ich.tier2', "foo.ich.tier2_1") 
    pubSub.subscribe('foo.ich.tier3', "foo.ich.tier2_1") 
    pubSub.subscribe("foo.ich.*", "All the ichs, all the time!") 

    #Find everything that starts with foo.ich 
    firedSubject = "foo.ich.tier2" 
    pubSub.fire(firedSubject) 
    #outputs 
    #>>Firing callback foo.bar 
    #>>callback foo.bar1 
    #>>Now with global subscriptions 
    # 
    #>>Firing callback foo.ich.tier2 
    #>>callback foo.ich.tier2_1 
    #>>global callback says All the ichs, all the time! 

這樣就好,沒有訴諸某種奇特的構造(例如嘗試)?我正在尋求一種肯定,即我正處於正確的軌道上,或者是一個純粹的Python(沒有外部庫或服務)的全球訂閱處理程序的更好的替代建議。

回答

1

這看起來像你在正確的軌道上給我。我正在使用PyPubSub和一個wxPython應用程序,然後最終實現了我自己的「更簡單」的版本,它的根本看起來和你在這裏完成的非常相似,除了你有更多的花裏胡哨的東西當你填寫你的要求時,你可能會最終執行。

給出的答案here也很像你所做的一樣。

answer進入有些不同的方法的例子。

PyPubSub外還有多個現有的庫,如pydispatchblinker,可能值得您參考或參考。