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

    Documento e caixa de entrada representando caixas de e-mail com mailbox no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    mailbox no Python: caixas de e-mail

    Aprenda mailbox no Python para ler, criar e migrar caixas Maildir, mbox e MH com locking, mensagens, flags e tratamento

    Ler mais

    Tempo de leitura: 6 minutos
    12/08/2026
    Editor de texto representando formatação com textwrap no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    textwrap no Python: formate textos

    Aprenda textwrap no Python para quebrar, preencher, encurtar, indentar e remover recuos de textos com controle de largura e espaços.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Pasta e lupa representando filtros de nomes com fnmatch no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    fnmatch no Python: filtre nomes de arquivos

    Aprenda fnmatch no Python para filtrar nomes de arquivos com curingas, controlar maiúsculas, excluir padrões e evitar confundir glob com

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Monitor com dados binários representando arrays numéricos compactos no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    array no Python: números compactos

    Aprenda array no Python para armazenar números compactos, manipular bytes, arquivos binários e buffers com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    10/08/2026
    Círculo cromático representando conversões RGB, HSV e HLS com colorsys no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    colorsys no Python: RGB, HSV e HLS

    Aprenda colorsys no Python para converter cores entre RGB, HSV, HLS e YIQ, gerar paletas e evitar erros com escalas

    Ler mais

    Tempo de leitura: 6 minutos
    09/08/2026
    Ícone de configuração representando arquivos plist com plistlib no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    plistlib no Python: arquivos plist

    Aprenda plistlib no Python para ler e gravar arquivos plist XML e binários, validar dados e integrar configurações Apple com

    Ler mais

    Tempo de leitura: 7 minutos
    08/08/2026