Decorator de cache para funções e métodos Python, com backends InMemory e SQLite, TTL configurável, hash estável de parâmetros e serialização segura.
Project description
PyCacheable
Decorator de cache para métodos e funções Python com backends em memória e SQLite — serialização automática com estratégia JSON-first + pickle fallback, hash estável de parâmetros, suporte a instância/estado e arquitetura plugável.
Problema
Em muitos aplicativos Python existem métodos que:
- fazem consultas repetidas ao banco de dados ou a APIs externas;
- recebem os mesmos parâmetros múltiplas vezes;
- repetem trabalho caro de CPU ou I/O;
- ou seja: fazem o mesmo trabalho mais de uma vez, desperdiçando tempo e recursos.
Sem um mecanismo de cache, cada chamada resulta em reexecução completa, levando a latências elevadas, carga extra no banco/serviço, e experiência de usuário piorada.
Solução
A biblioteca fornece:
- Um decorator
@cacheable(...)que envolve funções ou métodos, gera uma chave estável a partir dos parâmetros (serialização canônica + sha256); - Suporte a backends:
InMemoryCache: cache volátil em memória com LRU + TTL.SQLiteCache: cache persistente em disco (SQLite) com TTL, ideal para entre execuções ou processos;
- Logs claros de fluxo: HIT / MISS / EXPIRE — permitindo entender se o cache está funcionando;
- Serialização segura:
- JSON-first para estruturas simples (seguro, sem risco de RCE)
- Pickle fallback para objetos complexos (flexível)
- Métodos auxiliares:
.cache_clear(),.cache_info()no wrapper para inspeção/manutenção;
Como usar
from src.pycacheable.backend_sqlite import SQLiteCache
from src.pycacheable.backend_memory import InMemoryCache
from src.pycacheable.cacheable import cacheable
mem = InMemoryCache(max_entries=512)
disk = SQLiteCache(path="./.cache/myapp.sqlite")
class Repo:
@cacheable(ttl=60, backend=mem)
def get_user(self, user_id: int) -> dict:
# consulta cara ao banco
return {"user_id": user_id, "name": f"user{user_id}"}
@cacheable(ttl=300, backend=disk)
def get_orders(self, user_id: int, status: str = "open") -> list:
return [{"order_id": 101, "user_id": user_id, "status": status}]
repo = Repo()
u1 = repo.get_user(42) # MISS → executa consulta
u2 = repo.get_user(42) # HIT → retorna cache, consulta não é executada
Benefícios
- Menor latência em chamadas repetidas (hit quase instantâneo).
- Menor carga no banco/serviço, menos I/O repetido.
- Persistência local (via SQLite) permite cache entre reinícios/processos.
- Transparente para o usuário da função — apenas aplicar o decorator.
- Logs e métricas ajudam a monitorar impacto real.
- Serialização segura com JSON-first (sem risco de arbitrary code execution).
Quando usar
- Funções/métodos com resultado determinístico (mesmos parâmetros → mesmo resultado)
- Consultas idempotentes e repetidas
- Cálculos caros de CPU ou I/O
- Cenários onde latência importa e repetição deve ser evitada
Considerações e limites
- O cache evita reexecuções somente se os parâmetros para o método forem os mesmos e serializáveis.
- Se o método depende de estados mutáveis fora dos parâmetros (ex.:
self.some_state), você deve usarinclude_self=Trueou customkey_fn. - TTL é usado para expiração — resultados podem ficar "stale" se parâmetros ou contexto mudarem sem mudar a chave.
- Embora o backend SQLite seja persistente, ele não substitui um cache distribuído (ex.: Redis) em cenários multi-processo/semi-distribuídos.
- Pickle fallback mantém compatibilidade com objetos complexos, mas use com dados confiáveis.
Benchmarks
Veja resultados reais que medem MISS vs HIT:
| Backend | MISS (s) | HIT (s) | Speedup | Calls |
|---|---|---|---|---|
| RAW | 0.4410 | — | — | — |
| InMemory | 0.4043 | 0.000043 | ~9,494x | 1 |
| SQLite | 0.4001 | 0.000763 | ~524x | 1 |
O cache reduz o tempo de execução de ~0.4 s para ~0.00004 s — um speedup superior a 9.000×.
Próximos passos
- Suporte a funções
async def(decorator awaitable) - Backend Redis / LMDB para cenários distribuídos
- Métricas e integração com Prometheus
Licença
MIT License — veja o arquivo LICENSE para detalhes.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pycacheable-0.2.0.tar.gz.
File metadata
- Download URL: pycacheable-0.2.0.tar.gz
- Upload date:
- Size: 15.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cbd1191259e21c5393ec9985ab562a932ab35e40267349ac4b5312c565fb0192
|
|
| MD5 |
cad69ba9a0a9309a0be455d599f06d96
|
|
| BLAKE2b-256 |
6f5f906293d50af1e23b35aaf4ea718c5a1aa20673f45d764edbf6e3fc83c5c7
|
Provenance
The following attestation bundles were made for pycacheable-0.2.0.tar.gz:
Publisher:
publish.yml on leonardopinho/pycacheable
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycacheable-0.2.0.tar.gz -
Subject digest:
cbd1191259e21c5393ec9985ab562a932ab35e40267349ac4b5312c565fb0192 - Sigstore transparency entry: 2132145431
- Sigstore integration time:
-
Permalink:
leonardopinho/pycacheable@83bfe5334d3bb55a828ceb7eb5ebde6417138c7e -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/leonardopinho
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@83bfe5334d3bb55a828ceb7eb5ebde6417138c7e -
Trigger Event:
push
-
Statement type:
File details
Details for the file pycacheable-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pycacheable-0.2.0-py3-none-any.whl
- Upload date:
- Size: 12.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a71cee736e06eeb49973c699461cd8adc6eac83b840416a27735ab90c7ccf977
|
|
| MD5 |
e64df6409c5118bfcbe920328d7812ed
|
|
| BLAKE2b-256 |
bc451927f88691da4c615e947a7ccc9a137fcd17f1b79e68992326abacc4cf99
|
Provenance
The following attestation bundles were made for pycacheable-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on leonardopinho/pycacheable
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycacheable-0.2.0-py3-none-any.whl -
Subject digest:
a71cee736e06eeb49973c699461cd8adc6eac83b840416a27735ab90c7ccf977 - Sigstore transparency entry: 2132145545
- Sigstore integration time:
-
Permalink:
leonardopinho/pycacheable@83bfe5334d3bb55a828ceb7eb5ebde6417138c7e -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/leonardopinho
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@83bfe5334d3bb55a828ceb7eb5ebde6417138c7e -
Trigger Event:
push
-
Statement type: