36

私は@functools.lru_cachePython 3.3で使用しています。プログラムの再起動時にキャッシュを復元するために、キャッシュをファイルに保存したいと考えています。どうすればいいですか?

編集 1考えられる解決策:あらゆる種類の callable をピクルする必要があります

問題の酸洗__closure__:

_pickle.PicklingError: Can't pickle <class 'cell'>: attribute lookup builtins.cell failed

それなしで関数を復元しようとすると、次のようになります。

TypeError: arg 5 (closure) must be tuple
4

5 に答える 5

31

lru_cacheキャッシュにアクセスするための API が提供されておらず、将来のリリースで C で書き直される可能性があるため、を使用して必要なことを行うことはできません。本当にキャッシュを保存したい場合は、キャッシュにアクセスできる別のソリューションを使用する必要があります。

自分でキャッシュを書き込むのは簡単です。例えば:

from functools import wraps

def cached(func):
    func.cache = {}
    @wraps(func)
    def wrapper(*args):
        try:
            return func.cache[args]
        except KeyError:
            func.cache[args] = result = func(*args)
            return result   
    return wrapper

その後、デコレータとして適用できます。

>>> @cached
... def fibonacci(n):
...     if n < 2:
...             return n
...     return fibonacci(n-1) + fibonacci(n-2)
... 
>>> fibonacci(100)
354224848179261915075L

そして、以下を取得しますcache

>>> fibonacci.cache
{(32,): 2178309, (23,): 28657, ... }

次に、キャッシュを好きなようにピクル/ピクル解除して、次のようにロードできます。

fibonacci.cache = pickle.load(cache_file_object)

にダンプ/ロードを追加するという機能リクエストが Python の問題トラッカーで見つかりましたlru_cacheが、受け入れられず、実装もされませんでした。将来的には、これらの操作を を介して組み込みでサポートできるようになるかもしれませんlru_cache

于 2013-03-23T13:39:42.523 に答える
3

ディスクへの永続的なキャッシュにjoblib.Memoryを使用することを検討してください。

ディスクは非常に大きいため、LRU キャッシング スキームは必要ありません。

于 2014-05-05T16:53:28.790 に答える
1

public API を除いて、デコレーター実装の内部には何にも触れてはならないので、その動作を変更したい場合は、おそらくその実装をコピーして必要な機能を自分で追加する必要があります。キャッシュは現在、循環二重リンク リストとして保存されているため、保存と読み込みの際には注意が必要です。

于 2013-03-23T10:12:47.337 に答える