Apakah ada pustaka cache Python?

123

Saya mencari pustaka cache Python tetapi sejauh ini tidak dapat menemukan apa pun. Saya memerlukan dictantarmuka seperti sederhana di mana saya dapat mengatur kunci dan masa berlakunya dan mengembalikannya ke cache. Semacam sesuatu seperti:

cache.get(myfunction, duration=300)

yang akan memberi saya item dari cache jika ada atau memanggil fungsi dan menyimpannya jika tidak atau telah kedaluwarsa. Apakah ada yang tahu sesuatu seperti ini?

Stavros Korokithakis
sumber
saya pikir Anda hilang itemdalam contoh Anda.
SilentGhost
Ya, ini mungkin membutuhkan kunci ... Dan, 2.x.
Stavros Korokithakis
3
dalam proses yang sama atau dibagi antar proses? berulir atau tidak?
Aaron Watters
1
Ini harus thread-safe, maaf, seharusnya saya sebutkan. Saya tidak perlu berbagi antar proses.
Stavros Korokithakis
6
Coba DiskCache : berlisensi Apache2, cakupan 100%, aman utas, aman proses, kebijakan penggusuran ganda, dan cepat (tolok ukur) .
GrantJ

Jawaban:

72

Dari Python 3.2 Anda dapat menggunakan dekorator @lru_cache dari pustaka functools. Ini adalah cache yang Terakhir Digunakan Baru-Baru Ini, jadi tidak ada waktu kedaluwarsa untuk item di dalamnya, tetapi sebagai peretasan cepat, ini sangat berguna.

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)
Genma
sumber
20
cachetools menawarkan implementasi yang bagus dari ini dan itu kompatibel dengan python 2 dan python 3.
vaab
1
+1 besar untuk cachetools ... tampaknya cukup keren dan memiliki beberapa algoritme caching lainnya :)
Jörn Hees
Ini tidak boleh disarankan! Tetap kompatibel.
PascalVKooten
1
@roboslone, dua tahun (minus 4 hari ..) sejak komentar Anda tentang tidak amannya utas, mungkin telah berubah. Saya memiliki cachetools 2.0.0 dan saya melihat di kode yang menggunakan RLock. /usr/lib/python2.7/site-packages/cachetools/func.py
Motty
@Motty: Dokumentasi untuk cachetools 4.0.0.0 mengatakan ini: "Perlu diketahui bahwa semua kelas ini tidak aman untuk thread . Akses ke cache bersama dari beberapa thread harus disinkronkan dengan benar, misalnya dengan menggunakan salah satu dekorator memo dengan benda kunci yang sesuai "(tambang tebal)
martineau
28

Anda juga dapat melihat dekorator Memoize . Anda mungkin bisa membuatnya melakukan apa yang Anda inginkan tanpa terlalu banyak modifikasi.

tgray
sumber
Itu pintar. Sedikit perubahan dan dekorator bahkan bisa kedaluwarsa setelah waktu yang ditentukan.
Ehtesh Choudhury
Anda pasti bisa menulis batas berbasis ruang ke cache di dekorator. Itu akan sangat membantu jika Anda menginginkan suatu fungsi, misalnya, menghasilkan istilah urutan fibonacci. Anda ingin menyimpan ke cache, tetapi Anda hanya memerlukan dua nilai terakhir - menyimpan semuanya hanya tidak efisien ruang.
reem
14

Joblib https://joblib.readthedocs.io mendukung fungsi cache dalam pola Memoize. Sebagian besar, idenya adalah untuk menyimpan fungsi-fungsi yang mahal secara komputasi.

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

Anda juga dapat melakukan hal-hal mewah seperti menggunakan dekorator @ memory.cache pada fungsi. Dokumentasinya ada di sini: https://joblib.readthedocs.io/en/latest/generated/joblib.Memory.html

j13r
sumber
2
Sebagai catatan samping, joblib benar-benar bersinar saat Anda bekerja dengan array NumPy yang besar, karena ia memiliki metode khusus untuk menangani mereka secara khusus.
alexbw
12

Belum ada yang menyebutkan rak. https://docs.python.org/2/library/shelve.html

Ini tidak memcache, tetapi terlihat jauh lebih sederhana dan mungkin sesuai dengan kebutuhan Anda.

NuclearPeon
sumber
Saya menulis pembungkus thread- dan multiprocess-safe untuk modul rak standar (termasuk fungsi pembantu untuk caching permintaan http) jika itu berguna bagi siapa saja: github.com/cristoper/shelfcache
cristoper
9

Saya pikir API memcached python adalah alat yang lazim, tetapi saya belum menggunakannya sendiri dan tidak yakin apakah itu mendukung fitur yang Anda butuhkan.

David Berger
sumber
3
Itu adalah standar industri, tetapi yang saya inginkan hanyalah mekanisme penyimpanan dalam memori sederhana yang dapat menampung 100 kunci atau lebih, dan memcache agak berlebihan. Terima kasih atas jawabannya.
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)
Tzury Bar Yochay
sumber
5
Saya melakukan sesuatu seperti itu, tetapi Anda memerlukan kunci untuk multithreading dan parameter ukuran untuk menghindarinya tumbuh tanpa batas. Maka Anda memerlukan beberapa fungsi untuk mengurutkan kunci dengan akses untuk membuang kunci yang paling
jarang
Baris repr salah (harus menggunakan self.timeStamp). Selain itu, ini adalah implementasi yang buruk yang tidak perlu melakukan matematika untuk setiap get (). Waktu kedaluwarsa harus dihitung di CachedItem init.
ivo
1
Faktanya, jika Anda hanya mengimplementasikan getmetode, ini seharusnya tidak menjadi subkelas dict, itu haruslah sebuah objek dengan dict yang disematkan.
ivo
6

Anda dapat menggunakan solusi sederhana saya untuk masalah ini. Ini sangat mudah, tidak ada yang mewah:

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]

Memang tidak memiliki fungsi kedaluwarsa, tetapi Anda dapat dengan mudah memperluasnya dengan menetapkan aturan tertentu di c-tor MemCache.

Kode harapan cukup jelas, tetapi jika tidak, hanya untuk menyebutkan, cache itu diteruskan fungsi terjemahan sebagai salah satu parameter c-tornya. Ini digunakan pada gilirannya untuk menghasilkan output yang di-cache mengenai input.

Semoga membantu

Jakub Koszuliński
sumber
1
1 untuk menyarankan sesuatu yang sederhana. Bergantung pada masalahnya, itu mungkin hanya alat untuk pekerjaan itu. NB Anda tidak perlu elsemasuk __getitem__:)
hiwaylon
Mengapa dia tidak perlu elsedi __getitem__? Di situlah dia mengisi
dikt
5

Coba redis, ini adalah salah satu solusi terbersih dan termudah bagi aplikasi untuk berbagi data secara atomic atau jika Anda memiliki beberapa platform server web. Sangat mudah untuk mengaturnya, Anda memerlukan klien python redis http://pypi.python.org/pypi/redis

harry
sumber
1
Harus disebutkan, Ini keluar dari proses, perlu diakses menggunakan TCP.
jeffry copps
2

Lihat gocept.cache di pypi, kelola batas waktu.

Andreas Jung
sumber
2

Proyek ini bertujuan untuk menyediakan "Caching untuk manusia" (sepertinya cukup tidak diketahui)

Beberapa info dari halaman proyek:

Instalasi

pip instal cache

Pemakaian:

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()
Vano
sumber
-5

keyring adalah pustaka cache python terbaik. Kamu bisa memakai

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

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

json_res= keyring.core.delete_password("service","jsonkey")
imp
sumber
Itu adalah perpustakaan keyring, bukan perpustakaan cache.
Stavros Korokithakis
@StavrosKorokithakis Sebenarnya, saya mengimplementasikan caching kunci melalui keyring
imp