{"id":6556,"library":"cachier","title":"Persistent, Stale-Free Caching for Python Functions","description":"Cachier is a Python library that provides persistent, stale-free memoization decorators for Python functions. It supports various storage backends including local filesystem (pickle), in-memory, MongoDB, Redis, SQL, and S3, offering configurable cache expiration and automatic invalidation. The library is actively maintained with frequent releases, currently at version 4.2.0, and supports both synchronous and asynchronous functions.","status":"active","version":"4.2.0","language":"python","source_language":"en","source_url":"https://github.com/python-cachier/cachier","tags":["caching","memoization","decorator","performance","persistence","async"],"install":[{"cmd":"pip install cachier","lang":"bash","label":"Basic installation (pickle backend)"},{"cmd":"pip install cachier[redis,mongo,sql,s3]","lang":"bash","label":"Installation with all optional backend dependencies"}],"dependencies":[{"reason":"Core dependency for robust file locking in pickle backend.","package":"portalocker","optional":false},{"reason":"Optional dependency for more efficient file system event monitoring in pickle backend, especially on Linux.","package":"watchdog","optional":true},{"reason":"Required for the MongoDB caching backend.","package":"pymongo","optional":true},{"reason":"Required for the Redis caching backend.","package":"redis","optional":true},{"reason":"Required for the SQL (SQLAlchemy) caching backend.","package":"sqlalchemy","optional":true},{"reason":"Required for the S3 caching backend.","package":"boto3","optional":true}],"imports":[{"symbol":"cachier","correct":"from cachier import cachier"},{"note":"The `set_default_params` function is deprecated; use `set_global_params` instead for configuring global parameters.","wrong":"from cachier import set_default_params","symbol":"set_global_params","correct":"from cachier import set_global_params"}],"quickstart":{"code":"from cachier import cachier\nfrom datetime import timedelta\n\n@cachier(stale_after=timedelta(days=1))\ndef long_running_function(arg1, arg2):\n    \"\"\"This function's result will be cached for 1 day.\"\"\"\n    print(f\"Calculating result for {arg1}, {arg2}...\")\n    # Simulate a long computation\n    import time\n    time.sleep(1)\n    return arg1 + arg2\n\n# First call: calculates and caches the result\nprint(f\"Result 1: {long_running_function(10, 20)}\")\n\n# Second call (within 1 day): returns from cache instantly\nprint(f\"Result 2: {long_running_function(10, 20)}\")\n\n# To clear the cache for a specific function:\nlong_running_function.clear_cache()","lang":"python","description":"This quickstart demonstrates how to use the `cachier` decorator to add a persistent, time-based cache to a Python function. The first call computes the result, and subsequent calls within the `stale_after` period return the cached value instantly. It also shows how to manually clear a function's cache."},"warnings":[{"fix":"Be aware of this change when upgrading. Existing cache entries might need to be cleared or regenerated if function names were not implicitly part of your keying strategy.","message":"Starting with v3.0.0, cache keys now consider the function's name. If you upgrade from versions prior to 3.0.0 and relied on cache keys being agnostic to function names (e.g., if you copied and renamed functions), your existing cache entries might not be found or could cause collisions.","severity":"breaking","affected_versions":"<3.0.0 to 3.0.0+"},{"fix":"If using global enable/disable, verify its behavior after upgrading. If relying on cache file locations, check `~/.cache/cachier` (or `$XDG_CACHE_HOME/cachier`) and potentially migrate existing cache files.","message":"In v4.0.0, the `enable_caching()` and `disable_caching()` global functions now correctly affect *all* existing `@cachier` decorators. Previously, they might not have had an effect on decorators already applied. Additionally, `cachier` adopted the XDG Base Directory Specification for cache file locations, which might change the default cache directory (e.g., from `~/.cachier` to `~/.cache/cachier` on Linux).","severity":"breaking","affected_versions":"<4.0.0 to 4.0.0+"},{"fix":"For instance methods, use `@cachier(allow_non_static_methods=True)` or ensure the method is a `@staticmethod` or `@classmethod` if shared caching is not desired.","message":"By default, `cachier` will raise a `TypeError` when decorating an instance method (a method whose first parameter is named `self`). This is to prevent unintended cross-instance cache sharing. If you explicitly want cross-instance cache sharing for a method, you must pass `allow_non_static_methods=True` to the decorator.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure all arguments to cached functions are hashable. For functions with unhashable arguments, consider providing a custom `hash_func` to the decorator to generate a hashable key from the unhashable inputs.","message":"Functions decorated with `cachier` require all positional and keyword arguments to be hashable Python objects. If an unhashable argument is passed (e.g., a list or dictionary), a `TypeError` will be raised.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For optimal and correct async caching, ensure you are using backends and client configurations that natively support async operations, or understand the delegation behavior for your chosen backend.","message":"Asynchronous functions decorated with `cachier` will have their operations delegated to the synchronous implementation for many backends. Starting with v4.2.0, decorating async methods with sync-only engines of Redis, Mongo, and SQL cores is restricted and may lead to errors or unexpected behavior.","severity":"gotcha","affected_versions":"4.2.0+"},{"fix":"Pass `allow_none=True` to the decorator: `@cachier(allow_none=True)`.","message":"By default, `cachier` does not cache `None` values returned by a function. If your function can legitimately return `None` and you wish to cache it, you must explicitly enable this behavior.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'4.2.0':60 'activ':52 'async':73 'asynchron':66 'automat':47 'backend':29 'cach':5,44,68 'cachier':9 'configur':43 'current':57 'decor':21,70 'expir':45 'filesystem':32 'free':4,19 'frequent':55 'function':8,24,67 'in-memori':34 'includ':30 'invalid':48 'librari':13,50 'local':31 'maintain':53 'memoiz':20,69 'memori':36 'mongodb':37 'offer':42 'perform':71 'persist':1,16,72 'pickl':33 'provid':15 'python':7,12,23 'redi':38 'releas':56 's3':41 'sql':39 'stale':3,18 'stale-fre':2,17 'storag':28 'support':26,62 'synchron':64 'various':27 'version':59","created_at":"2026-04-15T18:32:57.717768+00:00","updated_at":"2026-04-16T01:16:30.223004+00:00","problems":[{"fix":"To explicitly allow caching of instance methods, pass `allow_non_static_methods=True` to the `@cachier` decorator. Ensure this is the desired behavior, as it means the cache will be shared across all instances of the object.\n\n```python\nfrom cachier import cachier\n\nclass Foo:\n    @cachier(allow_non_static_methods=True)\n    def my_method(self, arg1):\n        return arg1 * 2\n```","cause":"Cachier, by default, prevents caching of instance methods (functions with 'self' as the first parameter) to avoid unexpected behavior related to cross-instance cache sharing.","error":"TypeError: Cannot decorate instance methods without 'allow_non_static_methods=True'."},{"fix":"To instruct Cachier to cache `None` values, set `allow_none=True` in the `@cachier` decorator.\n\n```python\nfrom cachier import cachier\n\n@cachier(allow_none=True)\ndef function_returning_none(arg):\n    if arg > 0:\n        return arg\n    return None\n```","cause":"By default, Cachier does not cache `None` values, which can lead to unexpected cache misses if a function is expected to legitimately return `None`.","error":"Function return value is None, but cachier is not caching it."},{"fix":"Verify that the Redis server is running and accessible from the application's environment. Check the Redis configuration for the correct host and port, ensure no firewalls are blocking the connection (e.g., port 6379 for Redis), and confirm `cachier` is configured with the correct client or connection string for Redis.\n\n```python\n# Example for Redis in cachier, assuming redis_client is correctly initialized\nimport redis\nfrom cachier import cachier\n\n# Ensure your Redis server is running, e.g., 'redis-server'\n\n# Example of setting up cachier with a Redis client\nREDIS_CLIENT = redis.StrictRedis(host='localhost', port=6379, db=0)\n\n@cachier(backend='redis', redis_client=REDIS_CLIENT)\ndef my_cached_function_redis():\n    return \"Data from Redis\"\n```","cause":"This error indicates that the Python application cannot establish a connection with the Redis server, often because the server is not running, is configured to listen on a different address/port, or a firewall is blocking the connection.","error":"redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connection refused."},{"fix":"Increase the system's `inotify` watch limit. This is a system-level configuration, not a `cachier` code fix. Alternatively, consider using a different `cachier` backend like MongoDB or Redis if you anticipate a very large number of cached items, as they don't rely on `inotify` for cache file monitoring.\n\n```bash\n# To increase the inotify watch limit (e.g., to 524288)\n# Add this line to /etc/sysctl.conf\necho fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf\n\n# Apply the change\nsudo sysctl -p\n```","cause":"This error occurs on Linux systems when the default pickle backend of Cachier attempts to create too many `inotify` watches, typically when caching a very large number of distinct functions or keys, exceeding the system's `fs.inotify.max_user_watches` limit.","error":"OSError: inotify instance limit reached"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"4.2.0","cli_name":"","cli_version":null,"type":"library","homepage":"https://cachier.readthedocs.io","github":"https://github.com/python-cachier/cachier","docs":null,"changelog":null,"pypi":"https://pypi.org/project/cachier/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["database","data","http-networking"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-06-28","next_check":"2026-07-28","install_tag":null}}