2017-02-15 13 views
0

インスタンス化するのが非常に遅いオブジェクトがいくつかあります。それらはYAMLファイルのような外部ソースから読み込まれたデータの表現であり、大きなYAMLファイルの読み込みは遅いです(私はなぜか分かりません)。理想的には私が透明を希望Pythonでオブジェクトをキャッシュ/メモする方法は?

  • オブジェクトの作成時に
  • 環境変数
  • いくつかの外部ファイル

を渡される引数:

私はこれらのオブジェクトを知っているが、いくつかの外部要因に依存します外部要因が同じ場合、これらのオブジェクトをキャッシュする非定型メソッドです。

@cache(depfiles=('foo',), depvars=(os.environ['FOO'],)) 
class Foo(): 
    def __init__(*args, **kwargs): 
     with open('foo') as fd: 
      self.foo = fd.read() 
     self.FOO = os.environ['FOO'] 
     self.args = args 
     self.kwargs = kwargs 

主な考え方は、最初にFooをインスタンス化すると、オブジェクトの内容でキャッシュファイルが作成され、次回(別のPythonセッションで)インスタンス化するときにキャッシュファイルが使用されるだけです依存関係と引数のいずれも変更されていない場合

私がこれまでshelveに基づいて見つけた解決策:

import shelve 

class Foo(object): 
    _cached = False 
    def __new__(cls, *args, **kwargs): 
     cache = shelve.open('cache') 
     cache_foo = cache.get(cls.__name__) 
     if isinstance(cache_foo, Foo): 
      cache_foo._cached = True 
      return cache_foo 
     self = super(Foo, cls).__new__(cls, *args, **kwargs) 
     return self 

    def __init__(self, *args, **kwargs): 
     if self._cached: 
      return 

     time.sleep(2) # Lots of work 
     self.answer = 42 

     cache = shelve.open('cache') 
     cache[self.__class__.__name__] = self 
     cache.sync() 

あるとしてそれは完璧に動作しますが、それはあまりにも定型であり、それはすべてのケースをカバーしていない:

  • 異なるクラスが同じ名前を持つときの競合
  • argsとkwargsを確認
  • 依存関係(環境変数、外部ファイル)を確認する

ネイティブ Pythonで同様の動作を実現するソリューションはありますか?

+1

cachetools?私はそれについて知っている、それについては知らない。 https://pypi.python.org/pypi/cachetools – nigel222

+0

私はあなたがオブジェクトを酸洗してみることができると思います。 –

+0

@AlexFung 'shelve'はシーンの後ろに' pickle'を使います。 – nowox

答えて

1

Python 3はコールアウェアのメモを提供するためにデコレータを提供していますが、私はアプリケーションの複数回の実行中にキャッシュを保存しておきたいと思います。その時点で、そういうさまざまな要件がありそうです'one size fits all'ソリューションを見つけることができます。

あなた自身の答えが役に立つ場合は、それを使用してください。 「あまりにも多くの定型文」が残っているのであれば、別のmixinクラスにキャッシングを抽出することになります。Fooの最初の参照はclsとなるはずですが、cls.__name__ではなく__qualname__属性を使用してクラス名の競合の可能性(Python 3.3以降を想定)。

関連する問題