Pra que serve o __init__.py em Python?

Cansado de programar?

Conheça a melhor e mais completa formação de Python e Django e sinta-se um programador verdadeiramente competente. Além de Python e Django, você também vai aprender Banco de Dados, SQL, HTML, CSS, Javascript, Bootstrap e muito mais!

Quero aprender Python e Django de Verdade! Quero aprender!
Suporte

Tire suas dúvidas diretamente com o professor

Projetos práticos

Projetos práticos voltados para o mercado de trabalho

Prática profissional

Formação moderna com foco na prática profissional

Download do Artigo

✅ Artigo atualizado em Setembro 2026 Corrigimos a explicação sobre pacotes sem __init__.py (namespace packages, PEP 420) e sobre o __all__, completamos o exemplo que faltava e adicionamos resposta rápida, a diferença para o método __init__ das classes, tabela módulo vs pacote, erros comuns com traceback e 8 exercícios resolvidos. Saídas conferidas no Python 3.10 e 3.13.

Resposta rápida

O __init__.py é o arquivo que transforma uma pasta em pacote regular do Python. Ele roda automaticamente na primeira importação do pacote e serve para inicializá-lo, expor nomes (from .modulo import funcao) e definir __all__. Pode ficar vazio. Não confunda com o método __init__ das classes.

1
2
3
4
5
6
7
# loja/__init__.py
print("Inicializando o pacote loja")
from .precos import com_desconto   # loja/precos.py define com_desconto()

# main.py (fora da pasta loja)
import loja                        # Inicializando o pacote loja
print(loja.com_desconto(100))      # 90.0

Resumo em 30 segundos:

  • O arquivo __init__.py marca uma pasta como pacote; o método __init__ inicializa objetos de uma classe. Nomes iguais, papéis diferentes.
  • Ele é executado uma vez por processo, na primeira importação (inclusive ao importar só um submódulo, como from loja.precos import com_desconto).
  • Um __init__.py vazio já basta para ter um pacote regular.
  • Sem ele, desde o Python 3.3 a pasta vira namespace package (PEP 420): importa, mas sem código de inicialização.
  • O __all__ só afeta o from pacote import *; não torna nada privado.

Salve salve Pythonista!

Neste artigo, vamos entender pra que serve o arquivo __init__.py, quando ele é executado, o que colocar dentro dele e como resolver os erros de importação mais comuns em projetos com pacotes.

Se você chegou aqui procurando o def __init__(self) das classes, pule para a seção que explica a diferença entre os dois: o nome é parecido, mas o assunto é outro.

Então vamos nessa!

Vá Direto ao Assunto…

O que é o __init__.py?

O arquivo __init__.py é uma maneira de indicar ao Python que o diretório no qual ele se encontra deve ser tratado como um pacote regular (regular package).

No Python, um pacote é uma forma de estruturar os módulos (arquivos .py) de uma forma hierárquica.

Quando um pacote regular é importado, o seu __init__.py é executado automaticamente, e tudo o que ele define passa a fazer parte do namespace do pacote. A documentação oficial descreve esse comportamento na seção de pacotes do tutorial do Python e, em detalhes, na referência do sistema de importação (regular packages).

E sem o __init__.py? Desde o Python 3.3 (PEP 420), um diretório sem esse arquivo ainda pode ser importado, mas como um namespace package: um tipo especial de pacote que não executa código de inicialização, não tem __all__ e pode ser formado por “pedaços” espalhados em vários diretórios. Falamos mais sobre isso na seção Namespace Packages.

Na prática, para organizar o código do seu próprio projeto, o __init__.py continua sendo o caminho recomendado: ele deixa explícito que aquele diretório é um pacote e evita surpresas com ferramentas que só procuram pacotes regulares (como o find_packages() do setuptools).

Veja um exemplo:

1
2
3
4
5
6
7
# Estrutura de um projeto exemplo
meu_projeto/
    __init__.py
    modulo1.py
    subpacote/
        __init__.py
        modulo2.py

__init__.py vs método __init__ de uma classe

Muita gente busca “__init__ python” querendo uma coisa e encontra a outra. São dois assuntos diferentes que só dividem o nome (os dois sublinhados de cada lado são a convenção do Python para nomes especiais, os famosos dunders):

  • O arquivo __init__.py fica dentro de uma pasta e é executado quando o pacote é importado.
  • O método __init__ fica dentro de uma class e é executado a cada objeto criado. Ele é o inicializador (o “construtor”, no vocabulário de outras linguagens) e preenche os atributos em self. Explicamos esse método em detalhes no post sobre classes e objetos em Python, na seção do construtor.

Veja os dois no mesmo projeto, e a ordem em que cada um roda:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# loja/__init__.py  (ARQUIVO do pacote)
print("1) Rodando loja/__init__.py (arquivo do pacote)")

# loja/produto.py
class Produto:
    def __init__(self, nome, preco):  # MÉTODO __init__ (inicializador da classe)
        print(f"2) Rodando Produto.__init__ para {nome}")
        self.nome = nome
        self.preco = preco

# main.py (fora da pasta loja)
from loja.produto import Produto   # executa loja/__init__.py
caneta = Produto("Caneta", 2.5)    # executa Produto.__init__
print(caneta.nome, caneta.preco)

Saída ao rodar python main.py:

1
2
3
1) Rodando loja/__init__.py (arquivo do pacote)
2) Rodando Produto.__init__ para Caneta
Caneta 2.5
  Arquivo __init__.py Método __init__
Onde fica Dentro de uma pasta (pacote) Dentro de uma class
Quando roda Na primeira importação do pacote A cada objeto criado (Produto(...))
Quantas vezes Uma vez por processo Uma vez por instância
Para que serve Marcar a pasta como pacote, inicializar, expor nomes, __all__ Definir os atributos iniciais do objeto em self
Recebe parâmetros? Não Sim: self e os argumentos passados na criação

Formas de uso do __init__.py

Indicação de Pacotes

O uso mais simples do __init__.py é indicar ao Python que o diretório é um pacote.

Um __init__.py vazio já cumpre esse papel.

Por exemplo: supondo um diretório meu_projeto com estrutura mencionada acima, mesmo um __init__.py vazio permitirá importações.

Imagine que modulo1.py define a função ola() e subpacote/modulo2.py define a função tchau():

1
2
3
4
5
6
7
# meu_projeto/modulo1.py
def ola():
    return "Olá do modulo1!"

# meu_projeto/subpacote/modulo2.py
def tchau():
    return "Tchau do modulo2!"

Com os dois __init__.py vazios, um script que está no diretório acima de meu_projeto já consegue importar os módulos:

1
2
3
4
5
import meu_projeto.modulo1
from meu_projeto.subpacote import modulo2

print(meu_projeto.modulo1.ola())
print(modulo2.tchau())

E a saída será:

1
2
Olá do modulo1!
Tchau do modulo2!

Inicialização de Pacote

O __init__.py pode ser utilizado para realizar inicializações de pacotes. Isso é útil para configurar variáveis de ambiente, registros ou outras rotinas de inicialização:

1
2
3
4
5
6
# meu_projeto/__init__.py
print("Pacote 'meu_projeto' inicializado.")
CONFIG = {
    'versao': '1.0',
    'autor': 'Seu Nome'
}

Dessa forma, você pode importar a variável CONFIG com from meu_projeto import CONFIG e utilizar em qualquer lugar do seu código.

Definindo Exportações

Através do __init__.py, podemos definir quais nomes serão importados quando alguém usar from pacote import *.

Usamos a variável especial __all__ para indicar esses nomes/módulos:

1
2
# meu_projeto/__init__.py
__all__ = ['modulo1']

Com isso, o from meu_projeto import * passa a trazer apenas modulo1:

1
2
3
4
5
6
from meu_projeto import *
print(modulo1.ola())
print('subpacote' in dir())

from meu_projeto.subpacote import modulo2  # continua funcionando
print(modulo2.tchau())

E a saída será:

1
2
3
Olá do modulo1!
False
Tchau do modulo2!

Atenção: o __all__ só afeta o import *. Ele não esconde nada: importações explícitas, como import meu_projeto.subpacote ou from meu_projeto.subpacote import modulo2, continuam funcionando normalmente.

Importações Relativas

Dentro do __init__.py podemos usar importações relativas (com .) para trazer para o nível do pacote nomes definidos nos módulos internos. Assim, quem usa o pacote escreve from minha_aplicacao import funcao1 em vez de caminhos longos:

1
2
3
# minha_aplicacao/__init__.py
from .modulo1 import funcao1
from .subpacote.modulo2 import Classe2

Está curtindo esse conteúdo? :thumbsup:

Que tal receber 30 dias de conteúdo direto na sua Caixa de Entrada?

Sua assinatura não pôde ser validada.
Você fez sua assinatura com sucesso.

Assine as PyDicas e receba 30 dias do melhor conteúdo Python na sua Caixa de Entrada: direto e sem enrolação!

Exemplo Completo

Para demonstrar como o __init__.py é utilizado em um projeto, vamos criar uma estrutura de projeto mais completa.

Estrutura do Projeto

Essa será a estrutura do projeto que vamos utilizar para demonstrar o uso do arquivo __init__.py:

1
2
3
4
5
6
minha_aplicacao/
    __init__.py
    modulo1.py
    subpacote/
        __init__.py
        modulo2.py

Implementação

  • Arquivo minha_aplicacao/__init__.py
1
2
3
4
5
6
print("Pacote 'minha_aplicacao' inicializado.")

from .modulo1 import saudacao
from .subpacote.modulo2 import ClasseDeExemplo

__all__ = ['saudacao', 'ClasseDeExemplo']
  • Arquivo minha_aplicacao/modulo1.py
1
2
def saudacao():
    return "Olá do módulo 1!"
  • Arquivo minha_aplicacao/subpacote/__init__.py
1
# Pode estar vazio ou ter importações/inicializações específicas
  • Arquivo minha_aplicacao/subpacote/modulo2.py
1
2
3
4
5
6
class ClasseDeExemplo:
    def __init__(self):
        self.mensagem = "Classe de exemplo do módulo 2 no subpacote."

    def exibir_mensagem(self):
        return self.mensagem

:bulb: Criei o Ebookr.ai, uma plataforma que usa IA para gerar ebooks profissionais sobre qualquer tema - com capa gerada por IA, infográficos automáticos e exportação em PDF. Confere!

Utilização

Depois de criar a estrutura do nosso projeto, podemos importar e utilizar os módulos e classes conforme necessário:

1
2
3
4
5
6
# main.py (arquivo principal fora do pacote)
from minha_aplicacao import saudacao, ClasseDeExemplo

print(saudacao())
instancia = ClasseDeExemplo()
print(instancia.exibir_mensagem())

E a saída será (repare que a primeira linha vem do print do __init__.py, executado na importação):

1
2
3
Pacote 'minha_aplicacao' inicializado.
Olá do módulo 1!
Classe de exemplo do módulo 2 no subpacote.

Quando Usar all

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# __init__.py
__all__ = ['funcao_publica', 'ClassePublica']

def funcao_publica():
    return "Pública"

def _funcao_privada():
    return "Privada"

class ClassePublica:
    pass

class _ClassePrivada:
    pass

Quando alguém faz from pacote import *, apenas funcao_publica e ClassePublica serão importadas.

Isso não torna _funcao_privada inacessível: from pacote import _funcao_privada continua funcionando. O __all__ documenta a API pública e controla o import *, mas não é um mecanismo de privacidade.

Namespace Packages (Python 3.3+)

Desde Python 3.3 (PEP 420), um diretório sem __init__.py pode ser importado como namespace package. Ele funciona para importar módulos, mas é diferente de um pacote regular: não executa código de inicialização, não tem __file__ (vale None) e várias pastas com o mesmo nome em lugares diferentes do sys.path são combinadas num único pacote.

O uso pensado para namespace packages é dividir um mesmo pacote entre várias distribuições instaladas separadamente (por exemplo, plugins que compartilham o prefixo empresa.). Para o código do seu próprio projeto, prefira pacotes regulares. Resumindo:

✅ Use __init__.py quando:

  • Precisa inicializar o pacote
  • Quer controlar exports com __all__
  • Deseja imports simplificados

❌ Pode omitir quando:

  • Quer, de fato, um namespace package (pacote dividido entre várias pastas ou distribuições)
  • Entende que não terá inicialização nem __all__ naquele nível

Organizar um projeto em módulos e pacotes parece detalhe, mas é isso que separa código bagunçado de código profissional. Aprender essa organização na prática, com projetos guiados, é proposta da Jornada Python:

Módulo, pacote regular e namespace package: qual a diferença?

Um módulo é um único arquivo .py: tudo o que ele define (as funções, classes e variáveis) pode ser importado pelo nome do arquivo, sem a extensão. Um pacote é uma pasta que agrupa módulos e outros pacotes (subpacotes), acessados com ponto: loja.precos, loja.relatorios.vendas.

Na hora do import, o Python procura esses nomes nas pastas listadas em sys.path: a pasta do script que você executou, a biblioteca padrão e o site-packages, onde o pip instala as bibliotecas de terceiros (dentro do seu ambiente virtual, se você estiver usando um). Por isso o mesmo import loja pode funcionar num terminal e falhar em outro, como você vai ver em Erros comuns.

  Módulo Pacote regular Namespace package
O que é Um arquivo .py Uma pasta com __init__.py Uma pasta sem __init__.py (Python 3.3+)
Exemplo precos.py loja/__init__.py + loja/precos.py plugins/csv_plugin.py
Roda código ao importar? Sim, o próprio arquivo Sim, o __init__.py Não
Aceita __all__ no nível do pacote? Sim (no próprio arquivo) Sim Não
__file__ Caminho do .py Caminho do __init__.py None
Pode estar espalhado em várias pastas? Não Não Sim, pastas de mesmo nome no sys.path são combinadas
Quando usar Código pequeno ou uma responsabilidade só O padrão para organizar o código do seu projeto Plugins ou distribuições separadas que compartilham um prefixo

Erros comuns

Os exemplos abaixo usam esta estrutura (a pasta projeto/ é onde você abre o terminal):

1
2
3
4
5
6
7
projeto/
    loja/
        __init__.py
        precos.py        # def com_desconto(valor): return valor * 0.9
        relatorio.py
    scripts/
        gerar.py

1. ModuleNotFoundError: No module named 'loja'

Você roda um script que está em outra pasta e ele tenta importar o pacote:

1
2
3
4
# scripts/gerar.py
from loja.precos import com_desconto

print(com_desconto(50))
1
2
3
4
5
$ python scripts/gerar.py
Traceback (most recent call last):
  File "/home/voce/projeto/scripts/gerar.py", line 1, in <module>
    from loja.precos import com_desconto
ModuleNotFoundError: No module named 'loja'

Ao rodar python scripts/gerar.py, o Python coloca em sys.path a pasta do script (scripts/), e não a pasta de onde você chamou o comando. Como loja/ não está dentro de scripts/, o import falha. O mesmo erro aparece no terminal interativo ou com python -m se você estiver em outra pasta, fora de projeto/.

Correção: transforme scripts/ em pacote (crie um scripts/__init__.py vazio) e execute como módulo a partir de projeto/, com python -m scripts.gerar. Assim a pasta atual entra no sys.path e a saída é 45.0. Em projetos maiores, a solução definitiva é instalar o seu pacote no ambiente virtual (pip install -e .).

2. ImportError: attempted relative import with no known parent package

O arquivo usa import relativo (com ponto) e você o executa diretamente como script:

1
2
3
4
# loja/relatorio.py
from .precos import com_desconto

print(com_desconto(200))
1
2
3
4
5
$ python loja/relatorio.py
Traceback (most recent call last):
  File "/home/voce/projeto/loja/relatorio.py", line 1, in <module>
    from .precos import com_desconto
ImportError: attempted relative import with no known parent package

Rodado assim, o arquivo vira o módulo __main__ e o Python não sabe que ele pertence ao pacote loja, então o . não aponta para lugar nenhum.

Correção: a partir de projeto/, rode python -m loja.relatorio (saída: 180.0). Com -m, o Python importa loja primeiro (executando o loja/__init__.py) e o import relativo passa a funcionar.

3. Import circular entre o __init__.py e um módulo do pacote

O __init__.py importa um módulo, e esse módulo importa de volta algo definido no __init__.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# loja/__init__.py
from .produtos import Produto

def formatar_preco(valor):
    return f"R$ {valor:.2f}"

# loja/produtos.py
from loja import formatar_preco   # loja ainda não terminou de carregar!

class Produto:
    def __init__(self, nome, preco):
        self.nome = nome
        self.preco = preco

    def etiqueta(self):
        return f"{self.nome}: {formatar_preco(self.preco)}"

Um simples import loja resulta em (Python 3.10 a 3.12):

1
ImportError: cannot import name 'formatar_preco' from partially initialized module 'loja' (most likely due to a circular import) (/home/voce/projeto/loja/__init__.py)

No Python 3.13 a mensagem muda para ImportError: cannot import name 'formatar_preco' from 'loja' (consider renaming '.../loja/__init__.py' if it has the same name as a library you intended to import), mas a causa é a mesma: quando produtos.py pede formatar_preco, o __init__.py ainda está parado na linha 1 e a função não existe.

Correção: mova o código compartilhado para um módulo próprio e deixe o __init__.py só reexportar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# loja/formatacao.py
def formatar_preco(valor):
    return f"R$ {valor:.2f}"

# loja/produtos.py
from .formatacao import formatar_preco
# ... classe Produto igual à de cima

# loja/__init__.py
from .formatacao import formatar_preco
from .produtos import Produto

# main.py
from loja import Produto
print(Produto("Caneta", 2.5).etiqueta())   # Caneta: R$ 2.50

4. Esquecer que o __init__.py roda em toda importação

Qualquer import que passe pelo pacote executa o __init__.py antes, inclusive from pacote.submodulo import funcao. Código pesado ali deixa tudo lento:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# relatorios/__init__.py
import time

print("Carregando relatórios... (3 segundos)")
time.sleep(3)  # simula ler um arquivo grande ou abrir conexão com o banco
DADOS = [120, 80, 45]

# relatorios/util.py
def somar(valores):
    return sum(valores)

# main.py
import time

inicio = time.perf_counter()
from relatorios.util import somar  # só queria a função somar...
print(somar([1, 2, 3]))
print(f"Tempo: {time.perf_counter() - inicio:.1f}s")
1
2
3
Carregando relatórios... (3 segundos)
6
Tempo: 3.0s

Correção: deixe o __init__.py leve (imports, __all__, __version__) e coloque o trabalho pesado numa função chamada só quando for preciso:

1
2
3
4
5
6
7
8
9
10
11
12
# relatorios/__init__.py
import time

_dados = None

def carregar_dados():
    global _dados
    if _dados is None:
        print("Carregando relatórios... (3 segundos)")
        time.sleep(3)
        _dados = [120, 80, 45]
    return _dados

Com essa versão, o mesmo main.py imprime 6 e Tempo: 0.0s: os dados só são carregados quando alguém chama carregar_dados().

Exercícios resolvidos

Crie uma pasta vazia para os exercícios e rode cada main.py a partir dela. Em todos, os arquivos main.py ficam fora da pasta do pacote.

Exercício 1. Crie um pacote calc com um módulo operacoes.py que define somar(a, b). Em main.py, importe a função e imprima somar(2, 3).

Ver solução
1
2
3
4
5
6
7
8
9
10
# calc/__init__.py  -> arquivo vazio

# calc/operacoes.py
def somar(a, b):
    return a + b

# main.py
from calc.operacoes import somar

print(somar(2, 3))

Saída: 5

O __init__.py vazio já faz de calc um pacote regular, e o submódulo é acessado com ponto: calc.operacoes.

Exercício 2. Adicione ao pacote calc um módulo extras.py com dobro(x). Altere o calc/__init__.py para que from calc import somar, dobro funcione, sem citar os submódulos no main.py.

Ver solução
1
2
3
4
5
6
7
8
9
10
11
12
# calc/extras.py
def dobro(x):
    return x * 2

# calc/__init__.py
from .operacoes import somar
from .extras import dobro

# main.py
from calc import somar, dobro

print(somar(2, 3), dobro(10))

Saída: 5 20

Os imports relativos no __init__.py trazem as funções para o nível do pacote. É o mesmo truque que bibliotecas como o requests usam para você escrever requests.get em vez do caminho completo do módulo.

Exercício 3. (Estilo prova) Qual é a função do arquivo __init__.py em um diretório Python?

a) Definir o construtor das classes que estão no diretório.
b) Indicar que o diretório é um pacote regular e executar o código de inicialização dele na importação.
c) Permitir qualquer importação: sem ele, o Python 3 não importa a pasta de jeito nenhum.
d) Tornar privados todos os nomes que não estiverem no __all__.

Ver solução

Resposta: b.

A alternativa a descreve o método __init__ de uma classe. A c era verdade no Python 2, mas desde o Python 3.3 uma pasta sem __init__.py é importada como namespace package. A d está errada porque o __all__ só afeta o from pacote import *: from pacote import nome continua funcionando para qualquer nome.

Exercício 4. O pacote saudacoes tem só um __init__.py com print("Olá do __init__.py!"). Quantas vezes a mensagem aparece ao rodar o main.py abaixo?

1
2
3
4
import saudacoes
import saudacoes
from saudacoes import *
print("Fim")
Ver solução
1
2
Olá do __init__.py!
Fim

Só uma vez. Depois da primeira importação, o módulo fica guardado em sys.modules (você pode conferir com 'saudacoes' in sys.modules, que dá True) e as importações seguintes reutilizam o objeto já carregado, sem rodar o __init__.py de novo.

Exercício 5. (Estilo prova) Considere o pacote utilidades:

1
2
3
4
5
6
7
8
# utilidades/__init__.py
__all__ = ["limpar"]

def limpar(texto):
    return texto.strip().lower()

def contar(texto):
    return len(texto.split())

O que acontece ao executar o código abaixo?

1
2
3
4
from utilidades import *

print(limpar("  Olá Mundo  "))
print(contar("olá mundo"))

a) Imprime olá mundo e 2.
b) Imprime olá mundo e depois dá NameError.
c) Dá ImportError já na primeira linha, porque contar não está no __all__.
d) Dá AttributeError, porque contar é privada.

Ver solução

Resposta: b.

1
2
3
4
5
olá mundo
Traceback (most recent call last):
  File "/home/voce/exercicios/main.py", line 4, in <module>
    print(contar("olá mundo"))
NameError: name 'contar' is not defined

O import * só traz o que está em __all__, então contar não entra no namespace do main.py. Mas ela não é privada: from utilidades import contar funciona e contar("olá mundo") retorna 2.

Exercício 6. Com a estrutura abaixo, com os dois __init__.py vazios, por que o main.py falha? Corrija sem mexer no pacote.

1
2
3
4
5
6
7
8
9
10
# app/__init__.py          -> vazio
# app/banco/__init__.py    -> vazio
# app/banco/conexao.py
def conectar():
    return "conectado"

# main.py
import app

print(app.banco.conexao.conectar())
Ver solução

O erro é AttributeError: module 'app' has no attribute 'banco'. Importar um pacote não importa os subpacotes e submódulos automaticamente: o app/__init__.py está vazio, então app.banco nunca foi carregado. A correção é importar o caminho completo:

1
2
3
import app.banco.conexao

print(app.banco.conexao.conectar())

Saída: conectado

Outra opção seria o app/__init__.py importar o subpacote (from . import banco, e o banco/__init__.py fazer from . import conexao), mas o enunciado pedia para não mexer no pacote.

Exercício 7. Faça o pacote meupacote expor a versão "1.2.0" de forma que meupacote.__version__ funcione. Imprima também o nome do pacote.

Ver solução
1
2
3
4
5
6
7
8
# meupacote/__init__.py
__version__ = "1.2.0"

# main.py
import meupacote

print(meupacote.__version__)
print(meupacote.__name__)
1
2
1.2.0
meupacote

Tudo o que o __init__.py define vira atributo do pacote. Guardar __version__ ali é uma convenção antiga e muito comum em bibliotecas.

Exercício 8. Crie uma pasta plugins sem __init__.py, com um arquivo csv_plugin.py contendo NOME = "exportar_csv". O import funciona? O que plugins.__file__ mostra?

Ver solução
1
2
3
4
5
import plugins
import plugins.csv_plugin

print(plugins.__file__)
print(plugins.csv_plugin.NOME)
1
2
None
exportar_csv

Funciona, porque desde o Python 3.3 a pasta é importada como namespace package. O __file__ vale None porque não existe um __init__.py para apontar, e também não há código de inicialização nem __all__ no nível de plugins.

Quer praticar pacotes, módulos e imports montando projetos de verdade, com suporte de professor? Esse é o tipo de coisa que trabalhamos no nosso curso de Python completo, a Jornada Python.

Conclusão

Neste artigo, exploramos a funcionalidade e a importância do arquivo __init__.py em projetos Python.

Vimos que ele desempenha um papel crucial na indicação de pacotes, inicialização de pacotes e definição de exportações.

Além disso, através de exemplos práticos, mostramos como ele é utilizado na estruturação de projetos Python, tornando o código mais organizado e fácil de manter.

Para ver pacotes em ação num projeto real, confira o guia completo de Django: cada app criado com startapp é um pacote com seu próprio __init__.py. E para organizar imports e nomes de módulos, vale revisar o guia de estilos PEP 8.

Esperamos que este artigo tenha esclarecido quaisquer dúvidas sobre o __init__.py e motivado você a aplicá-lo corretamente em seus próprios projetos.

Valeu e até a próxima!

Perguntas frequentes

Pra que serve o __init__.py em Python?

O arquivo __init__.py transforma uma pasta em um pacote regular do Python. Ele é executado automaticamente na primeira vez que o pacote é importado e serve para inicializar o pacote, expor nomes dos módulos internos (por exemplo from .precos import com_desconto, permitindo from loja import com_desconto) e definir __all__. Um __init__.py vazio já basta para marcar a pasta como pacote.

O __init__.py é obrigatório no Python 3?

Não é obrigatório para importar. Desde o Python 3.3 (PEP 420), uma pasta sem __init__.py é importada como namespace package. Mas esse tipo de pacote não roda código de inicialização, não tem __all__ e __file__ vale None, e algumas ferramentas, como o find_packages() do setuptools, só encontram pacotes regulares. Para o código do seu próprio projeto, continue criando o __init__.py.

Qual a diferença entre o arquivo __init__.py e o método __init__ de uma classe?

São coisas diferentes que só compartilham o nome. O arquivo __init__.py fica dentro de uma pasta e é executado quando o pacote é importado. O método __init__, escrito como def __init__(self, ...) dentro de uma class, é o inicializador do objeto e roda a cada instância criada, por exemplo em Produto('Caneta', 2.5), para preencher atributos como self.nome.

O que colocar dentro do __init__.py?

Pode ficar vazio. Quando tiver conteúdo, o mais comum é: importar para o nível do pacote os nomes principais dos módulos internos (from .modulo import funcao), definir __all__ para controlar o from pacote import *, guardar metadados como __version__ = '1.0.0' e fazer inicializações leves. Evite código pesado (conexão com banco, leitura de arquivos grandes), porque ele roda em toda importação do pacote, inclusive de submódulos.

Quando o __init__.py é executado?

Na primeira vez que o pacote é importado no processo, seja com import pacote, from pacote import algo ou mesmo from pacote.submodulo import funcao. Depois disso o módulo fica guardado em sys.modules e novas importações reutilizam o que já foi carregado, sem executar o arquivo de novo.

Qual a diferença entre módulo e pacote em Python?

Um módulo é um único arquivo .py com funções, classes e variáveis, importado pelo nome do arquivo sem a extensão (import precos para precos.py). Um pacote é uma pasta que agrupa módulos e subpacotes; se tiver __init__.py é um pacote regular, se não tiver é um namespace package. Os submódulos são acessados com ponto, como em import loja.precos.

Como resolver ImportError: attempted relative import with no known parent package?

Esse erro aparece quando você roda como script um arquivo que usa import relativo, por exemplo python loja/relatorio.py com from .precos import com_desconto dentro. Rodado assim, o arquivo vira __main__ e perde a informação de que pertence ao pacote loja. A solução é executar a partir da pasta acima do pacote com python -m loja.relatorio, ou importar o módulo a partir de um script externo.

Em Python, qual é a função do arquivo __init__.py em um diretório?

Resposta de prova: indicar que o diretório é um pacote regular e executar o código de inicialização desse pacote quando ele é importado. Alternativas que costumam aparecer e estão erradas: ‘é o construtor das classes do diretório’ (isso é o método __init__), ‘é obrigatório para qualquer importação no Python 3’ (namespace packages dispensam o arquivo) e ‘torna privados os nomes fora do __all__’ (o __all__ só afeta o import *).

Começe agora sua Jornada na Programação!

Não deixe para amanhã o sucesso que você pode começar a construir hoje!

#newsletter Olá :wave: Curtiu o artigo? Então faça parte da nossa Newsletter! Privacidade Não se preocupe, respeitamos sua privacidade. Você pode se descadastrar a qualquer momento.