Python 캐싱 라이브러리가 있습니까?


123

Python 캐싱 라이브러리를 찾고 있지만 지금까지 아무것도 찾을 수 없습니다. dict키와 만료 시간을 설정하고 다시 캐시 할 수 있는 간단한 인터페이스 가 필요합니다 . 다음과 같은 종류입니다.

cache.get(myfunction, duration=300)

캐시 항목이 있으면 캐시에서 항목을 제공하거나 함수를 호출하고 만료되지 않았거나 만료 된 경우 저장합니다. 이런 걸 아는 사람 있나요?


나는 당신이 item당신의 모범을 놓치고 있다고 생각합니다 .
SilentGhost

네, 아마도 키가 필요할 것입니다 ... 그리고 2.x.
Stavros Korokithakis

3
동일한 프로세스 내에서 또는 프로세스간에 공유됩니까? 스레드 여부?
Aaron Watters

1
스레드로부터 안전해야합니다. 죄송합니다. 말씀 드렸어야합니다. 프로세스간에 공유 할 필요가 없습니다.
Stavros Korokithakis

6
DiskCache 사용해보기 : Apache2 라이선스, 100 % 적용 범위, 스레드 안전, 프로세스 안전, 다중 제거 정책 및 빠름 (벤치 마크) .
GrantJ

답변:



72

Python 3.2 에서는 functools 라이브러리 의 데코레이터 @lru_cache 를 사용할 수 있습니다 . 최근에 사용한 캐시이므로 항목에 대한 만료 시간이 없지만 빠른 해킹으로 매우 유용합니다.

from functools import lru_cache

@lru_cache(maxsize=256)
def f(x):
  return x*x

for x in range(20):
  print f(x)
for x in range(20):
  print f(x)

20
cachetools의 제공이의 좋은 구현을 그리고 3 호환 파이썬 2와 파이썬
vaab

1
cachetools에 대한 큰 일이 ... 정말 멋진 것 같습니다과 몇 가지 더 캐싱 알고리즘 :가
요른 HEES

이것은 결코 제안되어서는 안됩니다! 호환성을 유지하십시오.
PascalVKooten

1
@roboslone, 스레드로부터 안전하지 않다는 귀하의 의견으로부터 2 년 (마이너스 4 일 ..), 변경되었을 수 있습니다. 나는 cachetools 2.0.0을 가지고 있으며 RLock을 사용하는 코드를 볼 수 있습니다. /usr/lib/python2.7/site-packages/cachetools/func.py
Motty

@Motty : cachetools 4.0.0.0에 대한 문서 는 다음과 같이 말합니다. " 이러한 모든 클래스는 스레드로부터 안전하지 않습니다 . 여러 스레드에서 공유 캐시에 대한 액세스는 적절하게 동기화되어야합니다. 예를 들어 메모 데코레이터 중 하나를 사용하여 적합한 자물쇠 개체 "(굵은 광산)
martineau

28

Memoize 데코레이터를 살펴볼 수도 있습니다 . 너무 많은 수정없이 원하는 작업을 수행 할 수 있습니다.


영리하네요. 몇 가지 변경 사항과 데코레이터는 설정된 시간 후에 만료 될 수도 있습니다.
Ehtesh Choudhury 2013 년

데코레이터의 캐시에 공간 기반 제한을 확실히 쓸 수 있습니다. 예를 들어 피보나치 수열을 용어별로 생성하는 함수를 원할 경우 유용합니다. 캐싱을 원하지만 마지막 두 값만 필요합니다. 모든 값을 저장하는 것은 공간 비효율적입니다.
reem

14

Joblib https://joblib.readthedocs.io 는 Memoize 패턴에서 캐싱 기능을 지원합니다. 대부분의 아이디어는 계산 비용이 많이 드는 함수를 캐시하는 것입니다.

>>> from joblib import Memory
>>> mem = Memory(cachedir='/tmp/joblib')
>>> import numpy as np
>>> square = mem.cache(np.square)
>>> 
>>> a = np.vander(np.arange(3)).astype(np.float)
>>> b = square(a)                                   
________________________________________________________________________________
[Memory] Calling square...
square(array([[ 0.,  0.,  1.],
       [ 1.,  1.,  1.],
       [ 4.,  2.,  1.]]))
___________________________________________________________square - 0...s, 0.0min

>>> c = square(a)

함수에 @ memory.cache 데코레이터를 사용하는 것과 같은 멋진 작업을 수행 할 수도 있습니다. 문서는 여기에 있습니다 : https://joblib.readthedocs.io/en/latest/generated/joblib.Memory.html


2
부수적으로 joblib는 큰 NumPy 배열로 작업 할 때 실제로 빛을 발합니다. 그 이유는 특별히 처리하는 특별한 방법이 있기 때문입니다.
alexbw 2014


9

python memcached API 가 널리 사용되는 도구 라고 생각 하지만 직접 사용하지 않았으며 필요한 기능을 지원하는지 확실하지 않습니다.


3
그것은 업계 표준이지만 내가 원하는 것은 100 개 정도의 키를 저장할 수있는 간단한 메모리 내 저장 메커니즘이며 memcached는 약간 과잉입니다. 그래도 대답 해 주셔서 감사합니다.
Stavros Korokithakis

7
import time

class CachedItem(object):
    def __init__(self, key, value, duration=60):
        self.key = key
        self.value = value
        self.duration = duration
        self.timeStamp = time.time()

    def __repr__(self):
        return '<CachedItem {%s:%s} expires at: %s>' % (self.key, self.value, time.time() + self.duration)

class CachedDict(dict):

    def get(self, key, fn, duration):
        if key not in self \
            or self[key].timeStamp + self[key].duration < time.time():
                print 'adding new value'
                o = fn(key)
                self[key] = CachedItem(key, o, duration)
        else:
            print 'loading from cache'

        return self[key].value



if __name__ == '__main__':

    fn = lambda key: 'value of %s  is None' % key

    ci = CachedItem('a', 12)
    print ci 
    cd = CachedDict()
    print cd.get('a', fn, 5)
    time.sleep(2)
    print cd.get('a', fn, 6)
    print cd.get('b', fn, 6)
    time.sleep(2)
    print cd.get('a', fn, 7)
    print cd.get('b', fn, 7)

5
나는 그렇게했지만 멀티 스레딩에 대한 잠금과 무한히 커지는 것을 피하기 위해 크기 매개 변수가 필요합니다. 그런 다음 액세스가 가장 적은 키를 버리기 위해 액세스별로 키를 정렬하는 기능이 필요합니다.
Stavros Korokithakis

에 repr 선합니다 (self.timeStamp를 사용한다) 올바르지 않습니다. 또한 모든 get ()에 대해 불필요하게 수학을 수행하는 잘못된 구현입니다. 만료 시간은 CachedItem init에서 계산해야합니다.
ivo 2015 년

1
실제로 get메서드 만 구현하는 경우 dict 하위 클래스가 아니어야하며 포함 된 dict가있는 객체 여야합니다.
ivo

6

문제에 대한 간단한 해결책을 사용할 수 있습니다. 정말 간단하고 화려하지는 않습니다.

class MemCache(dict):
    def __init__(self, fn):
        dict.__init__(self)
        self.__fn = fn

    def __getitem__(self, item):
        if item not in self:
            dict.__setitem__(self, item, self.__fn(item))
        return dict.__getitem__(self, item)

mc = MemCache(lambda x: x*x)

for x in xrange(10):
    print mc[x]

for x in xrange(10):
    print mc[x]

실제로 만료 기능이 부족하지만 MemCache c-tor에서 특정 규칙을 지정하여 쉽게 확장 할 수 있습니다.

희망 코드는 충분히 자명하지만, 언급 할 필요가 없다면 해당 캐시는 c-tor 매개 변수 중 하나로 번역 함수를 전달하고 있습니다. 차례로 입력과 관련하여 캐시 된 출력을 생성하는 데 사용됩니다.

도움이되기를 바랍니다.


1
간단한 것을 제안하면 +1. 문제에 따라 작업을위한 도구 일 수도 있습니다. PS 당신은 필요하지 않습니다 else__getitem__:)
hiwaylon

왜이 필요하지 않을 else__getitem__? 그것이 그가 dict를 채우는 곳입니다 ...
Nils Ziehn

5

redis를 사용해보십시오. 애플리케이션이 원자 적 방식으로 데이터를 공유하거나 웹 서버 플랫폼이있는 경우 가장 깨끗하고 쉬운 솔루션 중 하나입니다. 설정이 매우 쉽고 Python redis 클라이언트 http://pypi.python.org/pypi/redis 가 필요합니다 .


1
언급해야합니다. 처리되지 않았으며 TCP를 사용하여 액세스해야합니다.
jeffry copps


2

프로젝트 는 "인간을위한 캐싱"을 제공하는 것을 목표로합니다 (하지만 꽤 알려지지 않은 것처럼 보입니다).

프로젝트 페이지의 일부 정보 :

설치

pip 설치 캐시

용법:

import pylibmc
from cache import Cache

backend = pylibmc.Client(["127.0.0.1"])

cache = Cache(backend)

@cache("mykey")
def some_expensive_method():
    sleep(10)
    return 42

# writes 42 to the cache
some_expensive_method()

# reads 42 from the cache
some_expensive_method()

# re-calculates and writes 42 to the cache
some_expensive_method.refresh()

# get the cached value or throw an error
# (unless default= was passed to @cache(...))
some_expensive_method.cached()


-5

keyring은 최고의 파이썬 캐싱 라이브러리입니다. 당신이 사용할 수있는

keyring.set_password("service","jsonkey",json_res)

json_res= keyring.get_password("service","jsonkey")

json_res= keyring.core.delete_password("service","jsonkey")

캐싱 라이브러리가 아니라 키링 라이브러리입니다.
Stavros Korokithakis

@StavrosKorokithakis 사실, 키링을 통해 키 캐싱을 구현했습니다
imp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.