代码之家  ›  专栏  ›  技术社区  ›  Paul Biggar

谷歌应用引擎单件(python)

  •  2
  • Paul Biggar  · 技术社区  · 15 年前

    在python中执行singleton的标准方法是

    class Singleton(object):
        _instance = None
        def __new__(cls, *args, **kwargs):
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
            return cls._instance
    

    但是,这在应用程序引擎上不起作用,因为可能有许多服务器,我们将为每个服务器获取一个实例。那么,对于一个应用引擎实体,我们该如何做呢?

    类似:

    class MySingleton(db.models):
        def __init__(self):
            all = MySingleton.all()
            if all.count() > 0:
                 return all.fetch(1).get()
    
            super(MySingleton, self).__init__ (*args, **kwargs)
    

    这会导致回避错误,因为 get() 电话 __init__ .

    我们将如何使用它 :

    我们只想表示一个配置文件,即:

    { 'sitename': "My site", 'footer': "This page owned by X"}
    
    4 回复  |  直到 12 年前
        1
  •  2
  •   dar    15 年前

    如果您不打算将数据存储在数据存储中,为什么不创建一个带有变量的模块而不是一个db.model?

    命名文件 mysettings.py 在里面写下:

    sitename = "My site"
    footer = "This page owned by X"
    

    然后,python模块实际上变成了一个“singleton”。如果需要,您甚至可以添加函数。要使用它,您可以这样做:

    import mysettings
    print mysettings.sitename
    

    Django就是这样处理这些问题的 DJANGO_SETTINGS_MODULE

    更新 以下内容: 听起来您真的想使用db.model,但是使用memcached,这样您只检索一次对象。但是,当您更改数据时,您必须想出一种方法来刷新它,或者让它有一个超时,以便偶尔得到它。我可能会使用超时版本,并在mysettings.py中执行类似的操作:

    from google.appengine.api import memcache
    class MySettings(db.Model):
       # properties...
    
    def Settings():
        key = "mysettings"
        obj = memcache.get(key)
        if obj is None:
           obj = MySettings.all().get()  # assume there is only one
           if obj:
                memcache.add(key, zone, 360)
           else:
                logging.error("no MySettings found, create one!")
        return obj
    

    或者,如果不想使用memcache,那么只需将对象存储在模块级变量中,并始终使用settings()函数来引用它。但是,在解释器实例被回收之前,您必须实现一种方法来刷新它。我通常会使用memcached来实现这种功能。

        2
  •  4
  •   Kylotan    15 年前

    单身通常是个坏主意,我想看看是什么让这成为一个例外。一般来说,他们只是伪装的全球人,除了所有与全球人有关的老问题(如 http://c2.com/cgi/wiki?GlobalVariablesAreBad 尤其是在顶部讨论非局部性、隐式耦合、并发性问题以及测试和限制的部分,在现代世界中,您会遇到由分布式和并发系统引起的额外问题。如果您的应用程序可能在多个服务器上运行,那么您是否可以让应用程序的两个实例在同一个单实例上安全、正确地运行呢?

    如果对象没有它的状态,那么答案是“是”,但是您不需要一个单例,只需要一个名称空间。

    但是如果对象确实有某种状态,您需要担心两个应用程序实例如何保持细节的同步。如果两个实例同时尝试读写同一个实例,那么结果可能是错误的。(例如,一个读取当前值、添加1并写入当前值的HitCounter单例计数器可能会以这种方式错过命中-这是我能想到的最不具破坏性的例子。)

    我基本上不熟悉它,所以也许谷歌应用引擎有一些事务逻辑来为你处理所有这些,但这可能意味着你必须添加一些额外的东西来处理回滚等。

    所以我的基本建议是,看看你是否可以在不使用单例的情况下重写算法或系统。

        3
  •  1
  •   Alex Martelli    15 年前

    __init__ 不能有效地 return 任何内容:就像第一个示例中一样,重写 __new__ 相反!

        4
  •  0
  •   Dave    12 年前

    我认为在运行多个实例的分布式环境中,没有真正的“singleton”对象可以保存。最接近的方法是使用memcache。

    也许最好少考虑单件事,多考虑数据一致性。对于此应用程序,引擎提供 transactions ,它允许您捕获实体中在使用该实体时可能发生的任何更改。