代码之家  ›  专栏  ›  技术社区  ›  rdrey

Django,Borg模式,API调用,缓存结果

  •  3
  • rdrey  · 技术社区  · 14 年前

    我正在使用一个来自不同站点的API,它返回一些我的用户用来购买虚拟商品的pricepointurl。

    在Python中查找singleton之后,我发现了borg模式,它看起来更酷,所以我做了以下工作:

    def fetchPrices():
        #uses urllib2.urlopen() to fetch prices
        #parses results with ElementTree
        return prices
    
    class PriceStore():
        __shared_state = {}
    
        def update(self):
            if self.lastUpdate is not None and (datetime.now() - self.lastUpdate).seconds >= 3600:
                self.prices = fetchPrices()
                self.lastUpdate = datetime.now()
            elif self.lastUpdate is not None:
                return
            else:
                self.lastUpdate = datetime.now() - timedelta(hours=1)
                self.update()
    
        def __init__(self):
            self.__dict__ = self.__shared_state
            self.lastUpdate = None
            self.update()
    

    我们的想法是通过以下方式使用它:

    store = PriceStore()
    url = store.prices['2.9900']['url']
    

    商店应该正确初始化,如果现有的信息早于一个小时,则只获取新的价格点信息。

    不过,每次初始化PriceStore时,我似乎都会碰到他们的API。有人能发现我的问题吗?我可以使用全局变量吗 __shared_state 在django,希望它仍然包含定价信息?

    3 回复  |  直到 14 年前
        1
  •  4
  •   Alex Martelli    14 年前

    我好像在和他们的API打交道 每次PriceStore 我的问题?

    是的,很容易发现:

    def __init__(self):
        self.__dict__ = self.__shared_state
        self.lastUpdate = None
    

    这个 self.lastUpdate = None 紧接着 self.update() 会发现 self.lastUpdate 的价值 None --你只是强迫它如此!

    去掉那个 __init__ 例如,使用

    lastUpdate = None
    

    类主体 __shared_state = {} 赋值和与该赋值相同的对齐方式。 那个 会让事情如你所愿。

        2
  •  1
  •   Ned Batchelder    14 年前

    class PriceStore():
        __shared_state = {'lastUpdate': None}
    

    您可能面临的另一个问题是,根据Django的部署方式,您可能会使用多个进程。每个人都有自己的共享状态副本。

        3
  •  0
  •   Katriel    14 年前

    __init__ self.lastUpdate = None . 别那么做。

    A = PriceStore()
    
    # some time later
    
    B = PriceStore()
    

    现在A.lastUpdate==None,这是您不想要的!相反,试试看

    if "lastUpdate" not in self.__dict__:
        self.lastUpdate = None
    

    这样你就不会覆盖它。