Estrutura de Projeto em Python: Por Que Usar o `src/`
Muitos projetos Python começam com arquivos na raiz. A estrutura `src/` pode parecer desnecessária no início, mas evita bugs sutis de importação e prepara seu projeto para empacotamento e testes.
O Problema Que Muitos Desenvolvedores Não Percebem
Ao iniciar um projeto Python, é comum colocar todos os arquivos na raiz:
my_project/
├── main.py
├── utils.py
├── config.py
Funciona.
Até deixar de funcionar.
Assim que você introduz testes, empacotamento ou instalação, as importações podem se comportar de forma diferente dependendo de como o código é executado.
Isso acontece porque o Python adiciona automaticamente o diretório atual ao sys.path.
Isso significa que a raiz do projeto se torna importável, mesmo que não devesse.
No começo, isso parece conveniente. Depois, se torna frágil.
A Armadilha Oculta das Importações
Considere esta importação:
from utils import helper_function
Ela funciona ao rodar a partir da raiz do projeto.
Mas após instalar o projeto como pacote, ou executar testes a partir de outro diretório, pode falhar com:
ImportError: No module named 'utils'
O motivo é simples.
Seu projeto nunca foi estruturado como um pacote instalável.
Ele funcionava apenas porque o Python incluía implicitamente a raiz no caminho de importação.
Isso pode mascarar problemas de empacotamento e gerar situações onde só funciona localmente.
A Estrutura src/
A estrutura src/ separa o código-fonte da raiz do projeto:
my_project/
├── src/
│ └── my_package/
│ ├── __init__.py
│ ├── main.py
│ └── utils.py
├── tests/
│ └── test_utils.py
├── pyproject.toml
Agora seu pacote vive dentro de src/, e as importações precisam referenciá-lo explicitamente:
from my_package import utils
Para garantir consistência, instale o projeto em modo editável:
pip install -e .
Assim, as importações se comportam da mesma forma em desenvolvimento, testes e produção.
Por Que a Estrutura src/ É Mais Segura
O principal benefício não é estético.
Ela evita importações acidentais a partir da raiz do projeto.
Se seus testes dependerem da raiz estar no sys.path, eles falharão imediatamente em vez de passarem silenciosamente.
Isso torna o projeto:
- Mais previsível
- Mais fácil de empacotar
- Mais confiável em CI
- Mais próximo do comportamento real em produção
Ela força correção desde cedo.
Quando Você Deve Usar
Você deve considerar fortemente a estrutura src/ se:
- Está construindo uma biblioteca
- Pretende publicar no PyPI
- Possui um arquivo
pyproject.toml - Mantém testes automatizados
- O projeto deve crescer
Para projetos de médio e longo prazo, normalmente vale a pena adotar.
Quando Não É Necessária
A estrutura src/ não é obrigatória em todos os cenários.
Pode ser desnecessária quando:
- Você está escrevendo um script único
- Está apenas experimentando ou prototipando
- O projeto não tem objetivos de empacotamento ou distribuição
Em scripts descartáveis, simplicidade pode ser mais importante do que estrutura.
Consideração Final
A estrutura src/ não é sobre adicionar complexidade.
É sobre evitar problemas sutis de importação e alinhar o desenvolvimento com o comportamento real dos pacotes instalados.
Para projetos sérios, ela cria disciplina e confiabilidade.
Para scripts rápidos, pode ser desnecessária.
O importante é escolher a estrutura de forma intencional, não por acaso.