aio-libs / aiocache

Asyncio cache manager for redis, memcached and memory
http://aiocache.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.09k stars 152 forks source link
asyncio cache cachemanager memcached python-3 redis

aiocache ########

Asyncio cache supporting multiple backends (memory, redis and memcached).

.. image:: https://travis-ci.org/argaen/aiocache.svg?branch=master :target: https://travis-ci.org/argaen/aiocache

.. image:: https://codecov.io/gh/argaen/aiocache/branch/master/graph/badge.svg :target: https://codecov.io/gh/argaen/aiocache

.. image:: https://badge.fury.io/py/aiocache.svg :target: https://pypi.python.org/pypi/aiocache

.. image:: https://img.shields.io/pypi/pyversions/aiocache.svg :target: https://pypi.python.org/pypi/aiocache

.. image:: https://api.codacy.com/project/badge/Grade/96f772e38e63489ca884dbaf6e9fb7fd :target: https://www.codacy.com/app/argaen/aiocache

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/ambv/black

This library aims for simplicity over specialization. All caches contain the same minimum interface which consists on the following functions:

.. role:: python(code) :language: python

.. contents::

.. section-numbering:

Installing

Usage

Using a cache is as simple as

.. code-block:: python

>>> import asyncio
>>> from aiocache import Cache
>>> cache = Cache(Cache.MEMORY) # Here you can also use Cache.REDIS and Cache.MEMCACHED, default is Cache.MEMORY
>>> with asyncio.Runner() as runner:
>>>     runner.run(cache.set('key', 'value'))
True
>>>     runner.run(cache.get('key'))
'value'

Or as a decorator

.. code-block:: python

import asyncio

from collections import namedtuple

from aiocache import cached, Cache
from aiocache.serializers import PickleSerializer
# With this we can store python objects in backends like Redis!

Result = namedtuple('Result', "content, status")

@cached(
    ttl=10, cache=Cache.REDIS, key="key", serializer=PickleSerializer(), port=6379, namespace="main")
async def cached_call():
    print("Sleeping for three seconds zzzz.....")
    await asyncio.sleep(3)
    return Result("content", 200)

async def run():
    await cached_call()
    await cached_call()
    await cached_call()
    cache = Cache(Cache.REDIS, endpoint="127.0.0.1", port=6379, namespace="main")
    await cache.delete("key")

if __name__ == "__main__":
    asyncio.run(run())

The recommended approach to instantiate a new cache is using the Cache constructor. However you can also instantiate directly using aiocache.RedisCache, aiocache.SimpleMemoryCache or aiocache.MemcachedCache.

You can also setup cache aliases so its easy to reuse configurations

.. code-block:: python

import asyncio

from aiocache import caches

You can use either classes or strings for referencing classes

caches.set_config({ 'default': { 'cache': "aiocache.SimpleMemoryCache", 'serializer': { 'class': "aiocache.serializers.StringSerializer" } }, 'redis_alt': { 'cache': "aiocache.RedisCache", 'endpoint': "127.0.0.1", 'port': 6379, 'timeout': 1, 'serializer': { 'class': "aiocache.serializers.PickleSerializer" }, 'plugins': [ {'class': "aiocache.plugins.HitMissRatioPlugin"}, {'class': "aiocache.plugins.TimingPlugin"} ] } })

async def default_cache(): cache = caches.get('default') # This always returns the SAME instance await cache.set("key", "value") assert await cache.get("key") == "value"

async def alt_cache(): cache = caches.create('redis_alt') # This creates a NEW instance on every call await cache.set("key", "value") assert await cache.get("key") == "value"

async def test_alias(): await default_cache() await alt_cache()

  await caches.get("redis_alt").delete("key")

if name == "main": asyncio.run(test_alias())

How does it work

Aiocache provides 3 main entities:

.. image:: docs/images/architecture.png :align: center

Those 3 entities combine during some of the cache operations to apply the desired command (backend), data transformation (serializer) and pre/post hooks (plugins). To have a better vision of what happens, here you can check how set function works in aiocache:

.. image:: docs/images/set_operation_flow.png :align: center

Amazing examples

In examples folder <https://github.com/argaen/aiocache/tree/master/examples>_ you can check different use cases:

Documentation

.. _redis: https://github.com/redis/redis-py .. _aiomcache: https://github.com/aio-libs/aiomcache