4 Summary: A least recently used (LRU) cache implementation
5 Home-page: https://github.com/jlhutch/pylru
7 Author-email: jlhutch+pylru@gmail.com
14 A least recently used (LRU) cache for Python.
19 Pylru implements a true LRU cache along with several support classes. The cache is efficient and written in pure Python. It works with Python 2.6+ including the 3.x series. Basic operations (lookup, insert, delete) all run in a constant amount of time. Pylru provides a cache class with a simple dict interface. It also provides classes to wrap any object that has a dict interface with a cache. Both write-through and write-back semantics are supported. Pylru also provides classes to wrap functions in a similar way, including a function decorator.
21 You can install pylru or you can just copy the source file pylru.py and use it directly in your own project. The rest of this file explains what the pylru module provides and how to use it. If you want to know more examine pylru.py. The code is straightforward and well commented.
29 An lrucache object has a dictionary like interface and can be used in the same way::
33 size = 100 # Size of the cache. The maximum number of key/value
34 # pairs you want the cache to hold.
36 cache = pylru.lrucache(size)
37 # Create a cache object.
39 value = cache[key] # Lookup a value given its key.
40 cache[key] = value # Insert a key/value pair.
41 del cache[key] # Delete a value given its key.
43 # These three operations affect the order of the cache.
44 # Lookup and insert both move the key/value to the most
45 # recently used position. Delete (obviously) removes a
46 # key/value from whatever position it was in.
48 key in cache # Test for membership. Does not affect the cache order.
50 value = cache.peek(key)
51 # Lookup a value given its key. Does not affect the
54 cache.keys() # Return an iterator over the keys in the cache
55 cache.values() # Return an iterator over the values in the cache
56 cache.items() # Return an iterator over the (key, value) pairs in the
59 # These calls have no effect on the cache order.
60 # lrucache is scan resistant when these calls are used.
61 # The iterators iterate over their respective elements
62 # in the order of most recently used to least recently
65 # WARNING - While these iterators do not affect the
66 # cache order the lookup, insert, and delete operations
67 # do. The result of changing the cache's order
68 # during iteration is undefined. If you really need to
69 # do something of the sort use list(cache.keys()), then
70 # loop over the list elements.
72 for key in cache: # Caches support __iter__ so you can use them directly
73 pass # in a for loop to loop over the keys just like
76 cache.size() # Returns the size of the cache
77 cache.size(x) # Changes the size of the cache. x MUST be greater than
78 # zero. Returns the new size x.
80 x = len(cache) # Returns the number of items stored in the cache.
81 # x will be less than or equal to cache.size()
83 cache.clear() # Remove all items from the cache.
86 Lrucache takes an optional callback function as a second argument. Since the cache has a fixed size, some operations (such as an insertion) may cause the least recently used key/value pair to be ejected. If the optional callback function is given it will be called when this occurs. For example::
90 def callback(key, value):
91 print (key, value) # A dumb callback that just prints the key/value
94 cache = pylru.lrucache(size, callback)
96 # Use the cache... When it gets full some pairs may be ejected due to
97 # the fixed cache size. But, not before the callback is called to let you
100 WriteThroughCacheManager
101 ------------------------
103 Often a cache is used to speed up access to some other high latency object. For example, imagine you have a backend storage object that reads/writes from/to a remote server. Let us call this object *store*. If store has a dictionary interface a cache manager class can be used to compose the store object and an lrucache. The manager object exposes a dictionary interface. The programmer can then interact with the manager object as if it were the store. The manager object takes care of communicating with the store and caching key/value pairs in the lrucache object.
105 Two different semantics are supported, write-through (WriteThroughCacheManager class) and write-back (WriteBackCacheManager class). With write-through, lookups from the store are cached for future lookups. Insertions and deletions are updated in the cache and written through to the store immediately. Write-back works the same way, but insertions are updated only in the cache. These "dirty" key/value pair will only be updated to the underlying store when they are ejected from the cache or when a sync is performed. The WriteBackCacheManager class is discussed more below.
107 The WriteThroughCacheManager class takes as arguments the store object you want to compose and the cache size. It then creates an LRU cache and automatically manages it::
112 cached = pylru.WriteThroughCacheManager(store, size)
114 cached = pylru.lruwrap(store, size)
115 # This is a factory function that does the same thing.
117 # Now the object *cached* can be used just like store, except caching is
118 # automatically handled.
120 value = cached[key] # Lookup a value given its key.
121 cached[key] = value # Insert a key/value pair.
122 del cached[key] # Delete a value given its key.
124 key in cache # Test for membership. Does not affect the cache order.
126 cached.keys() # Returns store.keys()
127 cached.values() # Returns store.values()
128 cached.items() # Returns store.items()
130 # These calls have no effect on the cache order.
131 # The iterators iterate over their respective elements
132 # in the order dictated by store.
134 for key in cached: # Same as store.keys()
136 cached.size() # Returns the size of the cache
137 cached.size(x) # Changes the size of the cache. x MUST be greater than
138 # zero. Returns the new size x.
140 x = len(cached) # Returns the number of items stored in the store.
142 cached.clear() # Remove all items from the store and cache.
145 WriteBackCacheManager
146 ---------------------
148 Similar to the WriteThroughCacheManager class except write-back semantics are used to manage the cache. The programmer is responsible for one more thing as well. They MUST call sync() when they are finished. This ensures that the last of the "dirty" entries in the cache are written back. This is not too bad as WriteBackCacheManager objects can be used in with statements. More about that below::
154 cached = pylru.WriteBackCacheManager(store, size)
156 cached = pylru.lruwrap(store, size, True)
157 # This is a factory function that does the same thing.
159 value = cached[key] # Lookup a value given its key.
160 cached[key] = value # Insert a key/value pair.
161 del cached[key] # Delete a value given its key.
163 key in cache # Test for membership. Does not affect the cache order.
166 cached.keys() # Return an iterator over the keys in the cache/store
167 cached.values() # Return an iterator over the values in the cache/store
168 cached.items() # Return an iterator over the (key, value) pairs in the
171 # The iterators iterate over a consistent view of the
172 # respective elements. That is, except for the order,
173 # the elements are the same as those returned if you
174 # first called sync() then called
175 # store.keys()[ or values() or items()]
177 # These calls have no effect on the cache order.
178 # The iterators iterate over their respective elements
179 # in arbitrary order.
181 # WARNING - While these iterators do not effect the
182 # cache order the lookup, insert, and delete operations
183 # do. The results of changing the cache's order
184 # during iteration is undefined. If you really need to
185 # do something of the sort use list(cached.keys()),
186 # then loop over the list elements.
188 for key in cached: # Same as cached.keys()
190 cached.size() # Returns the size of the cache
191 cached.size(x) # Changes the size of the cache. x MUST be greater than
192 # zero. Returns the new size x.
194 cached.clear() # Remove all items from the store and cache.
196 cached.sync() # Make the store and cache consistent. Write all
197 # cached changes to the store that have not been
200 cached.flush() # Calls sync() then clears the cache.
203 To help the programmer ensure that the final sync() is called, WriteBackCacheManager objects can be used in a with statement::
205 with pylru.WriteBackCacheManager(store, size) as cached:
206 # Use cached just like you would store. sync() is called automatically
207 # for you when leaving the with statement block.
211 ---------------------
213 FunctionCacheManager allows you to compose a function with an lrucache. The resulting object can be called just like the original function, but the results are cached to speed up future calls. The fuction must have arguments that are hashable::
221 cached = pylru.FunctionCacheManager(square, size)
225 # The results of cached are the same as square, but automatically cached
226 # to speed up future calls.
228 cached.size() # Returns the size of the cache
229 cached.size(x) # Changes the size of the cache. x MUST be greater than
230 # zero. Returns the new size x.
232 cached.clear() # Remove all items from the cache.
239 PyLRU also provides a function decorator. This is basically the same functionality as FunctionCacheManager, but in the form of a decorator::
241 from pylru import lrudecorator
247 # The results of the square function are cached to speed up future calls.
249 square.size() # Returns the size of the cache
250 square.size(x) # Changes the size of the cache. x MUST be greater than
251 # zero. Returns the new size x.
253 square.clear() # Remove all items from the cache.
256 Classifier: Programming Language :: Python :: 2.6
257 Classifier: Programming Language :: Python :: 2.7
258 Classifier: Programming Language :: Python :: 3
259 Classifier: Development Status :: 5 - Production/Stable
260 Classifier: Intended Audience :: Developers
261 Classifier: License :: OSI Approved :: GNU General Public License (GPL)
262 Classifier: Operating System :: OS Independent
263 Classifier: Topic :: Software Development :: Libraries :: Python Modules