Resolução de importações entre módulos e pacotes Python

Importando entre diretórios diferentes

Quando um projeto cresce, é comum dividir o código em pacotes organizados por responsabilidade. Suponha a seguinte estrutura:

aplicacao/
├── principal.py
└── pacotes/
    ├── utilitarios/
    │   ├── __init__.py
    │   └── texto.py
    └── modelos/
        ├── __init__.py
        └── dados.py

Se principal.py precisar usar o módulo texto.py, o importe absoluto funciona normalmente:

# principal.py
from pacotes.utilitarios import texto

texto.exibir_mensagem()

Entretanto, quando um módulo dentro de um subpacote precisa acessar outro subpacote paralelo, o importe pode falhar. Por exemplo, se dados.py tentar importar utilitarios.texto diretamente:

# pacotes/modelos/dados.py
from pacotes.utilitarios import texto

Ao executar dados.py, o Python pode gerar um erro informando que não encontra pacotes. Isso acontece porque o diretório raiz do projeto não está no sys.path. Uma solução prática é adicionar o caminho raiz dinamicamente:

# pacotes/modelos/dados.py
import sys
from pathlib import Path

raiz = Path(__file__).resolve().parent.parent.parent
sys.path.insert(0, str(raiz))

from pacotes.utilitarios import texto

def executar():
    texto.exibir_mensagem()

if __name__ == "__main__":
    executar()

Com a raiz inserida em sys.path, o Python consegue resolver o pacote corretamente. Essa abordagem funciona mesmo quando os módulos estão em unidades de disco distintas, desde que o caminho seja informado corretamente. Para evitar problemas com barras invertidas no Windows, prefira usar pathlib ao invés de concatenar strings manualmente.

Importando módulos de um mesmo pacote

Um pacote Python é simplesmente um diretório que contém um arquivo __init__.py. Esse arquivo pode estar vazio ou conter inicializações comuns. Veja o exemplo:

minipacote/
    __init__.py
    arq1.py
    arq2.py
teste.py

Conteúdo dos arquivos:

# minipacote/__init__.py
print("minipacote foi inicializado")

# minipacote/arq1.py
def exibir():
    print("Função do arquivo arq1")

# minipacote/arq2.py
def mostrar():
    print("Função do arquivo arq2")

# teste.py
from minipacote.arq1 import exibir
from minipacote.arq2 import mostrar

exibir()
mostrar()

Resultado esperado:

minipacote foi inicializado
Função do arquivo arq1
Função do arquivo arq2

O arquivo __init__.py é executado apenas uma vez, na primeira vez que o pacote é importado. Ele é útil para centralizar configurações e expor funcionalidades que devem estar disponíveis quando o pacote for utilizado.

Tags: Python Importação de Módulos sys.path __init__.py pacotes Python

Publicado em 7-23 04:06