Login

Cache any function (with its arguments)

Author:
bkroeze
Posted:
April 25, 2007
Language:
Python
Version:
.96
Tags:
cache function threading threads thread
Score:
6 (after 6 ratings)

Please see original snippet for commentary, all I did was add the caching of the arguments.

http://www.djangosnippets.org/snippets/109/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import cPickle as pickle
import md5

def cache_function(length):
    """
    A variant of the snippet posted by Jeff Wheeler at
    http://www.djangosnippets.org/snippets/109/
    
    Caches a function, using the function and its arguments as the key, and the return
    value as the value saved. It passes all arguments on to the function, as
    it should.
    
    The decorator itself takes a length argument, which is the number of
    seconds the cache will keep the result around.
    
    It will put in a MethodNotFinishedError in the cache while the function is
    processing. This should not matter in most cases, but if the app is using
    threads, you won't be able to get the previous value, and will need to
    wait until the function finishes. If this is not desired behavior, you can
    remove the first two lines after the ``else``.
    """
    def decorator(func):
        def inner_func(*args, **kwargs):
            from django.core.cache import cache
            
            raw = [func.__name__, func.__module__, args, kwargs]
            pickled = pickle.dumps(raw, protocol=pickle.HIGHEST_PROTOCOL)
            key = md5.new(pickled).hexdigest()
            value = cache.get(key)
            if cache.has_key(key):
                return value
            else:
                # This will set a temporary value while ``func`` is being
                # processed. When using threads, this is vital, as otherwise
                # the function can be called several times before it finishes
                # and is put into the cache.
                class MethodNotFinishedError(Exception): pass
                cache.set(key, MethodNotFinishedError(
                    'The function %s has not finished processing yet. This \
value will be replaced when it finishes.' % (func.__name__)
                ), length)
                result = func(*args, **kwargs)
                cache.set(key, result, length)
                return result
        return inner_func
    return decorator

More like this

  1. Cache Any Function by jeffwheeler 7 years, 11 months ago
  2. Language aware cache decorator by bartTC 5 years, 10 months ago
  3. Decorator cache handler per view by guicifuentes 6 years, 5 months ago
  4. Run and cache only one instance of a heavy request by farnsworth 4 years, 6 months ago
  5. Deferrable function cache decorator by bradbeattie 3 weeks ago

Comments

trbs (on May 1, 2008):

suggesting a try-except block around:

import cPickle as pickle

like such:

try:
    import cPickle as pickle
except ImportError:
    import pickle

To allow for fallback on pickle when cPickle is not accessible.

#

cazzerson (on July 27, 2008):

I am getting an error when I use this...

Can't pickle : attribute lookup django_snippet_cache_function.MethodNotFinishedError failed

Thanks...

#

Please login first before commenting.