Módulo 15 - Empacotamento e boas práticas
Estrutura de projeto e pacotes
9 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Diferenciar módulo, pacote e projeto.
- Entender o papel do arquivo __init__.py.
- Montar uma estrutura de pastas limpa para um projeto.
- Separar código, testes e configuração na raiz do projeto.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Estrutura de projeto e pacotes.
Os objetivos desta aula. Diferenciar módulo, pacote e projeto. Entender o papel do arquivo __init__.py. Montar uma estrutura de pastas limpa para um projeto. Separar código, testes e configuração na raiz do projeto.
Veja o essencial, parte por parte.
Módulo, pacote e projeto. Módulo é um arquivo .py; pacote é uma pasta de módulos.
O papel do __init__.py. Deixe-o vazio se o pacote é simples; a presença já basta para marcar o pacote.
A raiz do projeto. Na raiz do projeto, a regra de ouro é separar o que é código de produção do que é teste e do que é configuração.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
Módulo, pacote e projeto
Enquanto seu programa cabe num arquivo, organização não é problema. O problema começa quando ele cresce: centenas de funções soltas, nomes que se repetem, e ninguém acha nada. A solução é hierarquia. A menor unidade é o módulo, um arquivo .py que agrupa código relacionado. Quando vários módulos formam uma frente maior, você os junta numa pasta, que vira um pacote. E o conjunto de pacotes, mais os testes e a configuração, forma o projeto. Cada nível tem uma responsabilidade clara, e é essa clareza que deixa um código grande sustentável.
Pense num exemplo concreto: uma biblioteca de utilidades financeiras. As funções de juros vão para um módulo juros.py; as de formatação de moeda, para formatacao.py; as de datas, para datas.py. Todos ficam dentro de uma pasta financas, que é o pacote. Quem usa a biblioteca importa o que precisa, sabendo exatamente onde cada coisa mora. Essa arrumação não muda o que o código faz, mas muda tudo na hora de entender, alterar e reaproveitar.
| Nível | O que é | Exemplo |
|---|---|---|
| Módulo | Um arquivo .py | juros.py |
| Pacote | Uma pasta com módulos e __init__.py | financas/ |
| Subpacote | Pacote dentro de pacote | financas/relatorios/ |
| Projeto | A raiz, com código, testes e config | minha-biblioteca/ |
Os níveis de organização, do arquivo isolado ao projeto completo.
O papel do __init__.py
O arquivo __init__.py é o que, tradicionalmente, transforma uma pasta comum num pacote importável. Ele pode estar vazio, e muitas vezes está: a mera presença já sinaliza pacote. Mas ele também tem um papel útil, que é definir a fachada do pacote. Colocando alguns imports nele, você escolhe o que fica acessível direto pelo nome do pacote, sem a pessoa precisar saber em qual módulo interno cada coisa está. É a diferença entre expor uma interface limpa e obrigar quem usa a decorar sua organização interna.
# financas/__init__.py
# Expoe uma fachada limpa do pacote
from .juros import juros_compostos, juros_simples
from .formatacao import formatar_brl
__all__ = ["juros_compostos", "juros_simples", "formatar_brl"]
# Agora quem usa faz:
# from financas import juros_compostos, formatar_brl
# sem precisar saber que estao em juros.py e formatacao.pyO __init__.py define a fachada: o que o pacote expõe direto, escondendo a organização interna.
A raiz do projeto
Na raiz do projeto, a regra de ouro é separar o que é código de produção do que é teste e do que é configuração. Uma convenção muito usada é o layout src, em que todo o código do pacote fica dentro de uma pasta src, os testes numa pasta tests separada, e os arquivos de configuração, como o pyproject.toml e o README, ficam na raiz. Essa separação evita confusões sutis de import durante os testes e deixa óbvio, para qualquer pessoa que abre o projeto, onde está cada tipo de arquivo.
minha-biblioteca/
pyproject.toml # configuracao e metadados do projeto
README.md
src/
financas/
__init__.py
juros.py
formatacao.py
datas.py
tests/
test_juros.py
test_formatacao.pyLayout src: código em src/, testes em tests/, configuração na raiz. Cada coisa no seu lugar.
Repare que essa estrutura conta uma história. Quem chega ao projeto vê na hora que existe um pacote financas com três módulos, que há testes correspondentes, e que a configuração está na raiz. Não é preciso ler nenhum código para entender a forma do projeto. Essa legibilidade estrutural é tão importante quanto a legibilidade do código, e é ela que sustenta o trabalho em equipe e a manutenção ao longo dos anos. O projeto final do curso, aliás, nasce exatamente com esse layout.
Teste rápido
Qual a diferença entre um módulo e um pacote em Python?
Perguntas frequentes
- O __init__.py ainda é obrigatório nas versões novas do Python?
- Para pacotes comuns, ele deixou de ser estritamente obrigatório graças aos pacotes de namespace, mas continua sendo a prática recomendada. A presença do arquivo torna o pacote explícito, permite definir a fachada com imports e evita ambiguidades. Na dúvida, inclua-o.
- Por que separar o código numa pasta src?
- O layout src evita que os testes importem o pacote pela pasta do projeto por acidente, forçando-os a usar o pacote realmente instalado. Isso pega problemas de empacotamento cedo e deixa a estrutura mais clara, com código de produção, testes e configuração bem separados.
- Quando devo quebrar um módulo em vários?
- Quando ele começa a misturar responsabilidades diferentes ou fica grande demais para navegar. Se um arquivo junta juros, formatação e datas, vale separar por tema. A regra prática é que cada módulo deve ter um assunto claro que você consiga resumir numa frase.
- O que é o __all__ que aparece no __init__.py?
- É uma lista que declara os nomes públicos do módulo ou pacote. Ela define o que é exportado quando alguém faz from pacote import asterisco e documenta a interface oficial. É uma forma de dizer, com clareza, o que faz parte do contrato público e o que é interno.
- Preciso de uma estrutura de pacote para um script pequeno?
- Não. Um script de um arquivo não precisa de pacote nenhum. A estrutura entra quando o código cresce, ganha várias frentes e passa a ser reutilizado ou testado. Organizar cedo demais também atrapalha; organize quando a complexidade pedir.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.