在Python类中缓存数据(以避免在appengine上进行昂贵的文件系统读取)

2024-10-04 03:21:36 发布

您现在位置:Python中文网/ 问答频道 /正文

这个问题并不完全是appengine特有的,但它可能有助于了解上下文:我在appengine上有一种“静态站点生成器”,可以呈现页面,并允许它们通过各种主题和主题设置进行样式设置。主题当前直接存储在appengine文件系统中,并随应用程序一起上载。主题由几个模板和yaml配置数据组成。在

为了封装对主题的处理,我有一个Theme类。^例如,{}构造一个主题实例来加载和解析名为“sunshine”的主题的配置数据,并允许像theme.render_template('index.html')这样的调用自动加载并呈现文件系统上的正确文件。在

问题是,每次有新请求进来并实例化一个Theme时,加载并解析主题(yaml)的配置数据非常昂贵。所以,我想在processes/appengine实例中缓存数据,稍后可能会在memcached中缓存。在

到目前为止,我使用的缓存非常简单:

class Theme(object):
     _theme_variables_cache = {}

     def __init__(self, name):
         self.name = name

         if name not in Theme._theme_variables_cache:
             Theme._theme_variables[name] = self.load_theme_variables()

...

(我知道当多个请求同时命中构造函数时,可以多次读取配置。我不认为这会引起问题。)

但这种缓存很快就会变得丑陋。我想从配置文件中读取几个不同的东西,所有的缓存都是字典,因为每个不同的主题“name”也指向不同的底层配置。在

我的最后一个想法是创建一个类似Theme._cached_func(func)的函数,它只在函数结果尚未为特定模板缓存时执行func(请记住,当对象表示不同的模板时,缓存的值也可能不同)。所以我可以像这样使用它:self.theme_variables = Theme._cached_func(self.load_theme_variables()),但是,我有一种感觉,我在这里遗漏了一些明显的东西,因为我对Python还是相当陌生的。在

有没有一种明显而清晰的Python缓存模式可以在这种情况下工作,而不会用缓存逻辑扰乱整个类?我想我不能仅仅通过decorator或其他东西来记忆函数结果,因为不同的模板必须有不同的缓存。我甚至不需要任何“过时”的缓存处理,因为底层配置数据在进程运行时不会更改。在

更新

最后我就这样做了:

^{pr2}$

因此ThemeConfig存储从文件系统读取的主题的所有配置信息,而工厂方法ThemeConfig.get_for将始终为同一主题名称分发相同的ThemeConfig实例。我唯一的缓存逻辑是工厂方法中的一行,Theme对象仍然像以前一样是临时的和非共享的,所以我可以随意使用和滥用它们。在


Tags: 数据实例函数nameself模板yamlcache
1条回答
网友
1楼 · 发布于 2024-10-04 03:21:36

我要试试这个。基本上,在这里可以使用工厂模式来维护主题对象和以特定方式创建主题实例之间的清晰边界。在

工厂本身也可以通过存储主题名称和相应的主题对象之间的映射来维护简单的缓存策略。我将执行以下操作:

#the ThemeFactory class instantiates a Theme with a particular name if not present within it's cache
class ThemeFactory(object) :

     def __init__(self):
         self.__theme_variables_cache = {}

     def createTheme(self, theme_name):
         if not self.__theme_variables_cache.contains(name):
              theme = Theme(theme_name)
              self.__theme_variables_cache[name] = theme.load_theme_variables()
          return self.__theme_variables_cache[name]

主题类的定义现在非常干净和简单,不会包含任何缓存复杂性

^{pr2}$

该方法具有代码可维护性和明确的职责划分的优点(尽管不是完全如此,factory类仍然维护简单的缓存)。理想情况下,它应该只引用一个缓存服务或另一个处理缓存的类。。但你明白了)。在

你的主题类做得最好——加载主题变量。因为您有一个工厂模式,所以您将客户机代码(使用主题类实例的代码)封装在创建主题实例的逻辑中。随着应用程序的增长,您可以扩展这个工厂来控制各种主题对象的创建(包括从主题派生的类)

注意,这只是实现简单缓存行为和实例创建封装的一种方法。在

还有一点-可以在缓存中存储主题对象,而不是主题变量。这样,您就可以只在第一次使用时从模板中读取主题变量(延迟加载)。但是,在本例中,您需要确保将主题变量存储为主题类的实例变量。方法load_theme_variables(self)现在需要这样编写:

def load_theme_variables(self):
   #let the theme variables be stored in an instance variable __theme_variable
   if not self.__theme_variables is None:
       return self.__theme_variables
    #__read_theme_file is a private function that reads the theme files
   self__theme_variables = self.__read_theme_file(self.__theme_name)

希望这能给你一个关于如何实现你的用例的想法。在

相关问题 更多 >