Pickle Memo

This works like a regular memo, except it tries to pickle its results.

def pickle_memo(fn):
    name = fn.__name__
    qualname = fn.__qualname__
    memo_file = f"pickles/{qualname}.pickle"

    try:
        lookup = pickle.load(open(memo_file, 'rb'))
    except:
        print(f"Warning: could not load {memo_file!r}. Falling back to empty lookup.")
        lookup = {}

    def _wrapper(*args, **kw):
        key = frozenset((args, frozenset(kw.items())))

        if key in lookup:
            return lookup[key]

        result = fn(*args, **kw)
        lookup[key] = result
        pickle.dump(lookup, open(memo_file, "wb+"))

        return result

    _wrapper.__name__ = name

    return _wrapper

Example:

@pickle_memo
def slow_add_three(number):
    from time import sleep
    sleep(1)
    return number + 3


if __name__ == '__main__':
    for i in range(5):
        print(f"{i} + 3 =", slow_add_three(i))