Có thư viện bộ nhớ đệm Python không?


123

Tôi đang tìm thư viện bộ nhớ đệm Python nhưng không tìm thấy gì cho đến nay. Tôi cần một dictgiao diện giống như đơn giản , nơi tôi có thể đặt các khóa và thời hạn của chúng và khôi phục chúng vào bộ nhớ đệm. Đại loại như:

cache.get(myfunction, duration=300)

sẽ cung cấp cho tôi mục từ bộ nhớ cache nếu nó tồn tại hoặc gọi hàm và lưu trữ nó nếu nó không có hoặc đã hết hạn. Có ai biết một cái gì đó như thế này?


tôi nghĩ rằng bạn đang thiếu itemtrong ví dụ của bạn.
SilentGhost

Vâng, điều này có thể sẽ cần một khóa ... Và, 2.x.
Stavros Korokithakis

3
trong cùng một quy trình hay được chia sẻ giữa các quy trình? luồng hay không?
Aaron Watters

1
Nó phải là một chuỗi an toàn, xin lỗi, tôi nên đề cập đến. Tôi không cần phải chia sẻ giữa các quy trình.
Stavros Korokithakis

6
Hãy thử DiskCache : Apache2 được cấp phép, phạm vi phủ sóng 100%, an toàn theo chuỗi, an toàn cho quy trình, nhiều chính sách loại bỏ và nhanh (điểm chuẩn) .
GrantJ

Câu trả lời:


52

Ah, tôi tiếp tục tìm kiếm cái này và tất cả những gì tôi tìm thấy là một wiki đề cập đến cách sử dụng nó như một phần mềm trung gian WSGI. Nó giống như những gì tôi cần, cảm ơn bạn.
Stavros Korokithakis

7
Xem thêm dogpile - được cho là cốc có mỏ mới và cải tiến.
s29

72

Từ Python 3.2, bạn có thể sử dụng decorator @lru_cache từ thư viện functools. Đây là bộ đệm được sử dụng gần đây nhất, vì vậy không có thời gian hết hạn cho các mục trong đó, nhưng là một bản hack nhanh, nó rất hữu ích.

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 Mời một thực hiện tốt đẹp của những điều này và nó tương thích python 2 và python 3.
vaab

1
lớn 1 cho cachetools ... có vẻ khá mát mẻ và có một thuật toán bộ nhớ đệm vài chi tiết :)
Jörn Hees

Điều này không bao giờ nên được đề xuất! Giữ tương thích.
PascalVKooten

1
@roboslone, hai năm (trừ 4 ngày ..) kể từ nhận xét của bạn về việc không an toàn cho chuỗi, nó có thể đã thay đổi. Tôi có cachetools 2.0.0 và tôi thấy mã sử dụng RLock. /usr/lib/python2.7/site-packages/cachetools/func.py
Motty

@Motty: Tài liệu cho cachetools 4.0.0.0 cho biết điều này: "Xin lưu ý rằng tất cả các lớp này không an toàn cho luồng . Quyền truy cập vào bộ nhớ cache được chia sẻ từ nhiều luồng phải được đồng bộ hóa đúng cách, ví dụ: bằng cách sử dụng một trong các trình trang trí ghi nhớ với một đối tượng khóa phù hợp "(mỏ đậm)
martineau

28

Bạn cũng có thể xem qua trình trang trí Memoize . Bạn có thể có được nó để làm những gì bạn muốn mà không cần sửa đổi quá nhiều.


Thật khéo léo. Một vài thay đổi và trình trang trí thậm chí có thể hết hạn sau một thời gian nhất định.
Ehtesh Choudhury

Bạn chắc chắn có thể ghi giới hạn dựa trên không gian vào bộ nhớ cache trong trình trang trí. Điều đó sẽ hữu ích nếu bạn muốn một hàm, ví dụ, tạo ra thuật ngữ chuỗi fibonacci theo từng thuật ngữ. Bạn muốn bộ nhớ đệm, nhưng bạn chỉ cần hai giá trị cuối cùng - lưu tất cả chúng chỉ là không hiệu quả về dung lượng.
reem

14

Joblib https://joblib.readthedocs.io hỗ trợ các chức năng bộ nhớ đệm trong mẫu Memoize. Phần lớn, ý tưởng là lưu trữ các hàm tốn kém về mặt tính toán.

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

Bạn cũng có thể làm những việc ưa thích như sử dụng trình trang trí @ memory.cache trên các hàm. Tài liệu ở đây: https://joblib.readthedocs.io/en/latest/generated/joblib.Memory.html


2
Như một phụ chú, joblib thực sự tỏa sáng khi bạn đang làm việc với các mảng NumPy lớn, vì nó có các phương pháp đặc biệt để xử lý chúng một cách cụ thể.
alexbw

12

Chưa có ai đề cập đến giá đỡ. https://docs.python.org/2/library/shelve.html

Nó không phải là bộ nhớ đệm, nhưng trông đơn giản hơn nhiều và có thể phù hợp với nhu cầu của bạn.


Tôi đã viết một trình bao bọc an toàn luồng và đa quy trình cho mô-đun giá đỡ tiêu chuẩn (bao gồm chức năng trợ giúp cho các yêu cầu http vào bộ nhớ đệm) trong trường hợp hữu ích cho bất kỳ ai: github.com/cristoper/shelfcache
cristoper

9

Tôi nghĩ rằng API python memcached là công cụ phổ biến, nhưng bản thân tôi chưa sử dụng nó và không chắc liệu nó có hỗ trợ các tính năng bạn cần hay không.


3
Đó là tiêu chuẩn ngành, nhưng tất cả những gì tôi muốn là một cơ chế lưu trữ trong bộ nhớ đơn giản có thể chứa 100 khóa hoặc lâu hơn và memcached là một chút quá mức cần thiết. Cảm ơn bạn vì câu trả lời.
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
Tôi đã làm điều gì đó như vậy, nhưng bạn cần khóa cho đa luồng và một tham số kích thước để tránh nó phát triển vô hạn. Sau đó, bạn cần một số chức năng để sắp xếp các phím bằng cách truy cập để loại bỏ những người thân nhất-truy cập, vv vv ...
Stavros Korokithakis

Dòng repr không chính xác (nên sử dụng self.timeStamp). Ngoài ra, đó là một triển khai kém mà không cần toán học cho mỗi get (). Thời gian hết hạn phải được tính trong init CachedItem.
ivo

1
Trên thực tế, nếu bạn chỉ triển khai getphương thức, đây không phải là một lớp con dict, nó phải là một đối tượng với một dict được nhúng.
ivo

6

Bạn có thể sử dụng giải pháp đơn giản của tôi cho vấn đề. Nó thực sự đơn giản, không có gì hoa mỹ:

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]

Nó thực sự thiếu tính vui nhộn khi hết hạn, nhưng bạn có thể dễ dàng mở rộng nó bằng cách chỉ định một quy tắc cụ thể trong MemCache c-tor.

Mã hy vọng là đủ để tự giải thích, nhưng nếu không, chỉ cần đề cập, bộ nhớ cache đó đang được chuyển một chức năng dịch như một trong các tham số c-tor của nó. Nó được sử dụng lần lượt để tạo ra đầu ra được lưu trong bộ nhớ cache liên quan đến đầu vào.

Hy vọng nó giúp


1
+1 để đề xuất điều gì đó đơn giản. Tùy thuộc vào vấn đề, nó có thể chỉ là công cụ cho công việc. PS Bạn không cần elsein __getitem__:)
hiwaylon

Tại sao anh ta không cần phải elsetrong __getitem__? Đó là nơi anh ấy cư trú ...
Nils Ziehn

5

Hãy thử redis, đây là một trong những giải pháp sạch nhất và dễ dàng nhất cho các ứng dụng chia sẻ dữ liệu theo cách nguyên tử hoặc nếu bạn có một số nền tảng máy chủ web. Nó rất dễ cài đặt, bạn sẽ cần một ứng dụng khách python redis http://pypi.python.org/pypi/redis


1
Cần được đề cập, Nó nằm ngoài quy trình, cần được truy cập bằng TCP.
jeffry copps 17/12/18


2

Dự án này nhằm mục đích cung cấp "Bộ nhớ đệm cho con người" (có vẻ như nó khá chưa được biết đến)

Một số thông tin từ trang dự án:

Cài đặt

pip cài đặt bộ nhớ cache

Sử dụng:

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 là thư viện bộ nhớ đệm python tốt nhất. Bạn có thể dùng

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

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

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

Đó là thư viện keyring, không phải thư viện caching.
Stavros Korokithakis

@StavrosKorokithakis Trên thực tế, tôi thực hiện bộ nhớ đệm của các phím qua keyring
imp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.