Skip to content

Instantly share code, notes, and snippets.

@msiemens
Created March 12, 2013 15:40
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msiemens/5143963 to your computer and use it in GitHub Desktop.
Save msiemens/5143963 to your computer and use it in GitHub Desktop.
A simple Python file caching decorator, caching the function's response till the given file has been changed.
import os
import inspect
from functools import wraps
_file_cache = {}
def cache_file(path):
def cache_is_fresh(name):
return _file_cache[name]['MTIME'] == os.path.getmtime(path)
def func_has_args(func):
args, varargs, keywords, defaults = inspect.getargspec(func)
count = len(list(set(args) - set(['self']))) # Substract 'self' from
# args and count args
if varargs:
count += 1
if keywords:
count += 1
return count > 0
def decorator(f):
if func_has_args(f):
raise SyntaxWarning('cache_file doesn\'t support arguments')
name = f.__name__
@wraps(f)
def return_cache(*args, **kwargs):
if name in _file_cache.keys() and cache_is_fresh(name):
return _file_cache[name]['CONTENTS']
else:
# Store to cache
_file_cache[name] = {
'MTIME': os.path.getmtime(path),
'CONTENTS': f(*args, **kwargs)
}
return _file_cache[name]['CONTENTS']
return return_cache
return decorator
# Example:
counter = 0
@cache_file('/tmp/cached-file')
def my_func():
global counter
counter += 1
return counter
@Belissimo-T
Copy link

"self" is not always the name of the first argument of methods (same applies for "cls" in classmethods). It is just a convention. I would rather check if the function is a method/classmethod.

@msiemens
Copy link
Author

To be fair, when I wrote this I didn't have that much Python experience (this snippet is more than 9 years old now!). It worked back then but don't cosider this production ready code 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment