Skip to main content
Join the official 2019 Python Developers SurveyStart the survey!

A powerful caching library for Python, with TTL support and multiple algorithm options. (https://github.com/lonelyenvoy/python-memoization)

Project description

python-memoization

Version Supports Python Build Status Coverage Status Repository Downloads PRs welcome License

A powerful caching library for Python, with TTL support and multiple algorithm options.

Why choose this library?

Perhaps you know about functools.lru_cache in Python 3, and you may be wondering why I am reinventing the wheel.

Well, actually not. This lib is based on functools. Please find below the comparison with lru_cache.

Features functools.lru_cache memoization
Configurable max size ✔️ ✔️
Thread safety ✔️ ✔️
Flexible argument typing (typed & untyped) ✔️ Always typed
Cache statistics ✔️ ✔️
LRU (Least Recently Used) as caching algorithm ✔️ ✔️
LFU (Least Frequently Used) as caching algorithm No support ✔️
FIFO (First In First Out) as caching algorithm No support ✔️
TTL (Time-To-Live) support No support ✔️
Support for unhashable arguments (dict, list, etc.) No support ✔️
Partial cache clearing No support Pending implementation in v0.2.x
Python version 3.2+ 2.6, 2.7, 3.4+

memoization solves some drawbacks of functools.lru_cache:

  1. lru_cache does not support unhashable types, which means function arguments cannot contain dict or list.
>>> from functools import lru_cache
>>> @lru_cache()
... def f(x): return x
... 
>>> f([1, 2])  # unsupported
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
  1. lru_cache is vulnerable to hash collision attack and can be hacked or compromised. In memoization, caching is always typed, which means f(3) and f(3.0) will be treated as different calls and cached separately. This prevents the attack from happening (or at least makes it a lot harder).
>>> hash((1,))
3430019387558
>>> hash(3430019387558.0)  # two different arguments have an identical hash value
3430019387558

Installation

pip install memoization

Usage in 2 lines

from memoization import cached

@cached
def func(arg):
    ...  # do something slow

Simple enough - the results of func() are cached. Repetitive calls to func() with the same arguments run func() only once, enhancing performance.

Advanced features

Configurable options include ttl, max_size, algorithm and thread_safe.

TTL (Time-To-Live)

@cached(ttl=5)  # the cache expires after 5 seconds
def expensive_db_query(user_id):
    ...

For impure functions, TTL (in second) will be a solution. This will be useful when the function returns resources that is valid only for a short time, e.g. fetching something from databases.

Limited cache capacity

@cached(max_size=128)  # the cache holds no more than 128 items
def get_a_very_large_object(filename):
    ...

By default, if you don't specify max_size, the cache can hold unlimited number of items. When the cache is fully occupied, the former data will be overwritten by a certain algorithm described below.

Choosing your caching algorithm

from memoization import cached, CachingAlgorithmFlag

@cached(max_size=128, algorithm=CachingAlgorithmFlag.LFU)  # the cache overwrites items using the LFU algorithm
def func(arg):
    ...

Possible values for algorithm are:

  • CachingAlgorithmFlag.LRU: Least Recently Used (default)
  • CachingAlgorithmFlag.LFU: Least Frequently Used
  • CachingAlgorithmFlag.FIFO: First In First Out

This option is valid only when a max_size is explicitly specified.

Thread safe?

@cached(thread_safe=False)
def func(arg):
    ...

thread_safe is True by default. Setting it to False enhances performance.

Knowing how well the cache is behaving

>>> @cached
... def f(x): return x
... 
>>> f.cache_info()
CacheInfo(hits=0, misses=0, current_size=0, max_size=None, algorithm=<CachingAlgorithmFlag.LRU: 2>, ttl=None, thread_safe=True)

With cache_info, you can retrieve the number of hits and misses of the cache, and other information indicating the caching status.

  • hits: the number of cache hits
  • misses: the number of cache misses
  • current_size: the number of items that were cached
  • max_size: the maximum number of items that can be cached (user-specified)
  • algorithm: caching algorithm (user-specified)
  • ttl: Time-To-Live value (user-specified)
  • thread_safe: whether the cache is thread safe (user-specified)

Other APIs

  • Access the original function f by f.__wrapped__.
  • Clear the cache by f.cache_clear().

Contributing

This project welcomes contributions from anyone.

  • Submit bugs and help me verify fixes.
  • Submit pull requests for bug fixes and features and discuss existing proposals. Please make sure that your PR passes the tests in test/.

License

The MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for memoization, version 0.1.4
Filename, size File type Python version Upload date Hashes
Filename, size memoization-0.1.4-py3-none-any.whl (25.3 kB) File type Wheel Python version py3 Upload date Hashes View hashes
Filename, size memoization-0.1.4.tar.gz (24.1 kB) File type Source Python version None Upload date Hashes View hashes

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN SignalFx SignalFx Supporter DigiCert DigiCert EV certificate StatusPage StatusPage Status page