shelve no Python: persistência simples

Publicado em: 01/08/2026
Tempo de leitura: 5 minutos
Banco de dados local representando persistência com shelve no Python

O módulo shelve permite persistir objetos Python em um arquivo semelhante a um dicionário. Ele é útil quando você precisa guardar pequenas quantidades de dados entre execuções sem instalar um banco de dados. Embora simples, exige cuidados com segurança, concorrência e compatibilidade.

Quando usar shelve

Use shelve em scripts locais, protótipos, ferramentas pessoais, caches pequenos e aplicações de linha de comando. Ele oferece uma interface familiar: você abre uma prateleira, grava valores por chave e fecha o arquivo. Para sistemas web, múltiplos processos ou dados críticos, prefira SQLite, PostgreSQL ou outro banco transacional.

Exemplo básico

import shelve

with shelve.open("dados_app") as db:
    db["usuario"] = {"nome": "Ana", "nivel": 3}
    db["tema"] = "escuro"

with shelve.open("dados_app") as db:
    print(db["usuario"])

O contexto with garante o fechamento correto. Dependendo do sistema, vários arquivos podem ser criados com extensões diferentes. Por isso, trate o nome passado ao open como uma base, e não como um arquivo único.

Como funciona por dentro

shelve combina um banco chave-valor fornecido pelo módulo dbm com serialização via pickle. As chaves são strings. Os valores podem ser listas, dicionários, classes e outros objetos serializáveis. Essa flexibilidade é conveniente, mas significa que o conteúdo não é legível como JSON e não deve ser aberto a partir de fontes não confiáveis.

Atualização de objetos mutáveis

Uma armadilha comum ocorre ao alterar listas ou dicionários recuperados. Em geral, você deve atribuir o objeto de volta para que a mudança seja gravada.

with shelve.open("dados_app") as db:
    perfil = db["usuario"]
    perfil["nivel"] += 1
    db["usuario"] = perfil

Também existe a opção writeback=True, que mantém objetos acessados em cache e grava alterações ao fechar. Ela simplifica o código, mas pode consumir muita memória e aumentar o tempo de fechamento.

with shelve.open("dados_app", writeback=True) as db:
    db["usuario"]["nivel"] += 1

Use writeback apenas quando o volume for pequeno e você entender o custo. Em aplicações maiores, a atribuição explícita é mais previsível.

Operações úteis

A prateleira implementa operações de dicionário como keys(), values(), items(), get(), pop() e o operador in. Ainda assim, iterar por toda a base pode ser caro, porque cada valor precisa ser desserializado.

with shelve.open("dados_app") as db:
    if "contador" not in db:
        db["contador"] = 0
    db["contador"] = db.get("contador", 0) + 1
    for chave in db.keys():
        print(chave)

Flags de abertura

O parâmetro flag controla o comportamento de abertura. O valor padrão c abre para leitura e escrita, criando a base se necessário. r abre somente para leitura e exige que a base exista. w abre para leitura e escrita sem criar uma nova base. n sempre cria uma base vazia, apagando a anterior.

Em rotinas de leitura, prefira r para evitar criação acidental. Use n apenas em processos de reconstrução ou testes.

Segurança

Nunca abra uma prateleira recebida de usuários, baixada da internet ou modificada por terceiros. Como os valores usam pickle, dados maliciosos podem executar código durante a leitura. Mantenha os arquivos em diretórios controlados, com permissões restritas e fora de pastas públicas.

Também não armazene segredos sem criptografia. shelve não cifra o conteúdo. Tokens, senhas e chaves de API devem ficar em um gerenciador de segredos ou em armazenamento protegido.

Concorrência e integridade

O módulo não oferece uma estratégia portátil de bloqueio para múltiplos escritores. Duas instâncias gravando ao mesmo tempo podem corromper a base. A regra mais segura é ter apenas um processo escritor. Se precisar compartilhar dados entre processos, use SQLite ou um serviço de banco de dados.

Mesmo com um único escritor, interrupções bruscas podem deixar arquivos inconsistentes. Faça cópias de segurança antes de alterações importantes e considere gravar em uma base temporária antes de substituir a versão principal.

Compatibilidade e migração

A implementação dbm varia entre sistemas operacionais. Um conjunto de arquivos criado em uma máquina pode não abrir em outra. Além disso, objetos pickle dependem de classes, módulos e versões compatíveis. Se você renomear uma classe ou alterar sua estrutura, valores antigos podem falhar.

Para dados que precisam durar anos, viajar entre plataformas ou ser lidos por outras linguagens, use formatos como JSON, CSV ou um banco estável. shelve é melhor como solução local e controlada.

Padrão de repositório simples

from pathlib import Path
import shelve

class Repositorio:
    def __init__(self, caminho: Path):
        self.caminho = str(caminho)

    def salvar(self, chave: str, valor) -> None:
        with shelve.open(self.caminho) as db:
            db[chave] = valor

    def obter(self, chave: str, padrao=None):
        with shelve.open(self.caminho, flag="c") as db:
            return db.get(chave, padrao)

    def remover(self, chave: str) -> bool:
        with shelve.open(self.caminho) as db:
            if chave not in db:
                return False
            del db[chave]
            return True

Encapsular o acesso reduz erros, centraliza o caminho e facilita uma futura migração para SQLite. Também permite adicionar validação, logs e cópias de segurança sem espalhar detalhes pelo projeto.

Testes

Nos testes, use um diretório temporário com tempfile.TemporaryDirectory. Assim você evita poluir o projeto e garante isolamento.

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as pasta:
    repo = Repositorio(Path(pasta) / "teste")
    repo.salvar("x", {"valor": 10})
    assert repo.obter("x")["valor"] == 10

Boas práticas

Use chaves estáveis e documentadas. Valide os objetos antes de gravar. Feche sempre a base com with. Evite writeback em conjuntos grandes. Não compartilhe um escritor entre processos. Mantenha backups quando os dados tiverem valor. Planeje uma migração quando o projeto crescer.

Alternativas

JSON é melhor para dados simples e portáveis. SQLite oferece transações, consultas e concorrência mais segura. dbm armazena bytes e exige serialização manual. Bibliotecas como SQLModel e SQLAlchemy são adequadas quando o domínio cresce.

Conclusão

shelve é uma ferramenta prática para persistência local com uma API de dicionário. Ela reduz código em pequenos projetos, mas não substitui um banco de dados. Use-a em ambientes controlados, nunca confie em arquivos externos e migre para uma solução transacional quando surgirem múltiplos processos, consultas ou requisitos fortes de durabilidade.

Leia também zipfile no Python, tempfile no Python, tomllib no Python e copy no Python. Consulte a documentação oficial de shelve e o aviso de segurança do pickle.

Antes de adotar a solução, registre quais dados serão persistidos, por quanto tempo e como serão recuperados em caso de falha. Essa pequena decisão arquitetural evita que um protótipo vire dependência crítica sem monitoramento. Inclua uma rotina de exportação para JSON e teste periodicamente a restauração em outra máquina.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Documentos de texto representando comparação de versões com difflib no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    difflib no Python: compare textos e arquivos

    Aprenda difflib no Python para comparar textos, medir similaridade, criar diffs unificados, relatórios HTML e sugestões de nomes.

    Ler mais

    Tempo de leitura: 7 minutos
    01/08/2026
    Painel de gráficos representando análise estatística de dados no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    statistics no Python: análise de dados

    Aprenda statistics no Python para média, mediana, desvio padrão, quantis, correlação, regressão, NormalDist e KDE.

    Ler mais

    Tempo de leitura: 8 minutos
    31/07/2026
    Gráficos de frações representando números racionais exatos no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    fractions no Python: números racionais

    Aprenda fractions no Python para cálculos racionais exatos, simplificação, limit_denominator, formatação e conversões seguras.

    Ler mais

    Tempo de leitura: 7 minutos
    31/07/2026
    Calculadora e documentos representando cálculos decimais precisos no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    Decimal no Python: cálculos precisos

    Aprenda Decimal no Python para cálculos exatos, dinheiro, quantize, arredondamento, contextos e validação sem erros de float.

    Ler mais

    Tempo de leitura: 8 minutos
    30/07/2026
    Código digital representando identificadores UUID únicos e ordenáveis no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    uuid no Python: IDs únicos e ordenáveis

    Aprenda uuid no Python: versões 4, 5, 6 e 7, validação, bancos de dados, IDs ordenáveis e cuidados de segurança.

    Ler mais

    Tempo de leitura: 8 minutos
    30/07/2026
    Arquivos organizados representando armazenamento temporário seguro no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    tempfile no Python: arquivos temporários

    Aprenda tempfile no Python para criar arquivos e pastas temporárias com segurança, limpeza automática e suporte a Windows e Unix.

    Ler mais

    Tempo de leitura: 8 minutos
    29/07/2026