Чи є бібліотека кешування Python?


123

Я шукаю бібліотеку кешування Python, але поки нічого не можу знайти. Мені потрібен простий dictінтерфейс, у якому я можу встановити клавіші та їх закінчення та отримати кешування. Сортування чогось типу:

cache.get(myfunction, duration=300)

який дасть мені елемент із кеша, якщо він існує, або зателефонуйте у функцію та збережіть його, якщо його немає або закінчився термін дії. Хтось знає щось подібне?


я думаю, ти пропускаєш itemу своєму прикладі.
SilentGhost

Так, для цього, мабуть, знадобиться ключ ... І, 2.x.
Ставрос Корокітакіс

3
в рамках одного і того ж процесу або спільного між процесами? різьбові чи ні?
Аарон Уоттерс

1
Це повинно бути безпечним для потоків, вибачте, я мав би згадати. Мені не потрібно ділитися між процесами.
Ставрос Корокітакіс

6
Спробуйте DiskCache : ліцензія Apache2, 100% покриття, безпека для потоків, безпечна для процесів, багаторазова політика виселення та швидка робота (орієнтири) .
GrantJ

Відповіді:


52

Ах, я постійно шукав це, і все, що я знайшов, - це вікі, в якому згадувалося, як використовувати його як проміжне програмне забезпечення WSGI. Схоже, що мені потрібно, дякую.
Ставрос Корокітакіс

7
Дивіться також доггіл - нібито новий і вдосконалений стакан.
s29

72

З Python 3.2 ви можете використовувати декоратор @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 пропонує приємну реалізацію цього, і він сумісний з python 2 та python 3.
vaab

1
великий +1 для cachetools ... здається досить крутим і має ще кілька алгоритмів кешування :)
Jörn Hees

Це ніколи не слід підказувати! Будьте сумісні.
PascalVKooten

1
@roboslone, два роки (мінус 4 дні ..) з вашого коментаря про те, що це не безпечно для потоків, можливо, це змінилося. У мене є cachetools 2.0.0, і я бачу в коді, що він використовує RLock. /usr/lib/python2.7/site-packages/cachetools/func.py
Motty

@Motty: Документація для cachetools 4.0.0.0 говорить про це: "Будь ласка, майте на увазі, що всі ці класи не є безпечними для потоків . Доступ до спільного кешу з декількох потоків повинен бути належним чином синхронізований, наприклад, за допомогою одного з декораторів запам'ятовування з підходящий замок об’єкт "(сміливий міну)
мартіно

28

Ви також можете поглянути на декоратора пам’яті . Можливо, ви могли б змусити його робити те, що хочете, без надто великих змін.


Це розумно. Кілька змін, і декоратор може навіть закінчитися через встановлений час.
Ehtesh Choudhury

Ви, безумовно, можете записати обмеження на кеш-пам’яті для кеша в декораторі. Це було б корисно, якби ви хотіли, щоб функція, наприклад, генерувала порядок послідовності вирівнень за терміном. Ви хочете кешувати, але вам потрібні лише останні два значення - збереження всіх них просто неефективно.
reem

14

Joblib https://joblib.readthedocs.io підтримує функції кешування у шаблоні "Пам'ятати". Здебільшого ідея полягає в кешуванні обчислювально дорогих функцій.

>>> 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

12

Полиці ніхто ще не згадав. https://docs.python.org/2/library/shelve.html

Він не запам’ятовується, але виглядає набагато простіше і може відповідати вашим потребам.


Я написав обгортку для безпечного потоку та багатопроцесорів для стандартного модуля полки (включаючи функцію помічника для кешування запитів http) у випадку, що корисно для будь-кого: github.com/cristoper/shelfcache
cristoper

9

Я думаю, що API-інтерфейс python - це найпоширеніший інструмент, але я сам його не використовував і не впевнений, чи підтримує він потрібні функції.


3
Це галузевий стандарт, але все, що я хочу, - це простий механізм зберігання в пам'яті, який може вмістити 100 клавіш або близько того, а запам’ятовування - це трохи надмірне. Дякую за відповідь, хоча.
Ставрос Корокітакіс

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
Я робив щось подібне, але вам потрібні блокування для багатопотокової роботи та параметр розміру, щоб не зростати нескінченно. Тоді вам потрібна якась функція, щоб сортувати клавіші за доступом, щоб відкинути найменш доступні, і т.
Д.

Рядок repr неправильний (слід використовувати self.timeStamp). Крім того, це погана реалізація, яка марно робить математику для кожного get (). Час закінчення терміну дії повинен бути обчислений в inched CachedItem.
ivo

1
Насправді, якщо ви реалізуєте лише getметод, це не повинен бути підклас диктату, це повинен бути об'єкт із вбудованим діктом.
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__? Ось де він заповнює
дикту

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 - найкраща бібліотека кешування python. Можна використовувати

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

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

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

Це бібліотека брелоків, а не бібліотека кешування.
Ставрос Корокітакіс

@StavrosKorokithakis Насправді я здійснив кешування клавіш за допомогою keyring
imp
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.