Pergunta

O que é __init__.py em um diretório de origem Python?

Foi útil?

Solução

Ela costumava ser uma parte necessária de um pacote ( velho, pre -3.3 "pacote regular" , não mais recente 3.3+ "namespace pacote ").

Aqui está a documentação.

Python define dois tipos de pacotes, pacotes regulares e pacotes de namespace. pacotes regulares são pacotes tradicionais como existiram em Python 3.2 e anteriores. Um pacote regular é normalmente implementado como um diretório que contém um arquivo __init__.py. Quando um pacote regular é importado, este arquivo __init__.py é implicitamente executado, e os objetos que ele define são obrigados a nomes namespace do pacote. O arquivo __init__.py podem conter o mesmo código Python que qualquer outro módulo pode conter, e Python irá adicionar alguns atributos adicionais para o módulo quando ele é importado.

Mas basta clicar no link, ele contém um exemplo, obter mais informações, e uma explicação de pacotes de nomes, o tipo de pacotes sem __init__.py.

Outras dicas

__init__.py Arquivos nomeados são usados ??para diretórios marca no disco como diretórios pacote Python. Se você tem os arquivos

mydir/spam/__init__.py
mydir/spam/module.py

e mydir está no seu caminho, você pode importar o código no module.py como

import spam.module

ou

from spam import module

Se você remover o arquivo __init__.py, Python não vai mais olhar para submódulos dentro desse diretório, então tentativas de importar o módulo irá falhar.

O arquivo __init__.py é geralmente vazia, mas pode ser usado para exportar partes selecionadas do pacote sob o nome mais conveniente, funções de conveniência de retenção, etc. Dado o exemplo acima, os conteúdos do módulo de init pode ser acedida como

import spam

este

Além de rotular um diretório como um pacote Python e definindo __all__, __init__.py permite definir qualquer variável no nível do pacote. Fazer isso é muitas vezes conveniente se um define pacote algo que será importado com frequência, de uma forma API-like. Este padrão promove a adesão ao Pythonic "flat é melhor do que aninhados" filosofia.

Um exemplo

Aqui está um exemplo de um dos meus projetos, em que eu freqüentemente importar um sessionmaker chamado Session para interagir com meu banco de dados. Eu escrevi um pacote de "banco de dados" com alguns módulos:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

Meu __init__.py contém o seguinte código:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Desde que eu definir Session aqui, posso iniciar uma nova sessão usando a sintaxe abaixo. Este código seria o mesmo executado a partir de dentro ou fora do "banco de dados" diretório do pacote.

from database import Session
session = Session()

Claro, este é um pequeno conveniência - a alternativa seria definir Session em um novo arquivo como "create_session.py" no meu pacote de banco de dados, e iniciar novas sessões usando:

from database.create_session import Session
session = Session()

Leitura

Há um fio reddit bastante interessante cobrindo usos apropriados de __init__.py aqui:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

A opinião da maioria parece ser que os arquivos __init__.py deve ser muito fina para evitar violar o "explícito é melhor do que implícito" filosofia.

Existem 2 principais razões para __init__.py

  1. Por conveniência: os outros usuários não precisam saber localização exata de seus funções na sua hierarquia de pacotes

    .
    your_package/
      __init__.py
      file1.py
      file2.py
        ...
      fileN.py
    
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    
    # in file1.py
    def add():
        pass
    

    , em seguida, outros podem chamar add () por

    from your_package import add
    

    sem saber file1, como

    from your_package.file1 import add
    
  2. Se você quer algo para ser inicializado; por exemplo, o registo (que deve ser colocado no nível superior):

    import logging.config
    logging.config.dictConfig(Your_logging_config)
    

O arquivo __init__.py faz diretórios tratar Python contendo-o como módulos.

Além disso, este é o primeiro arquivo a ser carregado em um módulo, para que você possa usá-lo para executar o código que você deseja executar cada vez que um módulo é carregado, ou especificar os submódulos a ser exportado.

Desde Python 3.3, __init__.py não é mais necessário para definir diretórios como pacotes Python importáveis.

Verifique PEP 420: Pacotes Namespace implícitas :

O suporte nativo para diretórios de pacotes que não exigem arquivos marcador __init__.py e podem medir automaticamente vários segmentos de caminho (inspirado por vários terceiros abordagens para pacotes de nomes, como descrito em PEP 420 )

Aqui está o teste:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

referências:
https://docs.python.org/3 /whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
__init__.py não é necessária para pacotes no Python 3?

Em Python a definição de pacote é muito simples. Como Java da estrutura hierárquica e a estrutura de diretórios são os mesmos. Mas você tem que ter __init__.py em um pacote. Vou explicar o arquivo __init__.py com o exemplo abaixo:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py pode estar vazio, desde que ela existe. Ele indica que o diretório deve ser considerado como um pacote. Claro, __init__.py também pode definir o conteúdo apropriado.

Se somarmos uma função em module_n1:

def function_X():
    print "function_X in module_n1"
    return

Depois de executar:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

Depois, seguimos o pacote hierarquia e chamou module_n1 a função. Podemos usar __init__.py em subPackage_b assim:

__all__ = ['module_n2', 'module_n3']

Depois de executar:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

Assim, usando * importação, pacote do módulo está sujeito a conteúdo __init__.py.

Embora Python funciona sem um arquivo __init__.py você deve ainda incluir um.

especifica um pacote deve ser tratado como um módulo, de modo que, por conseguinte, inclui-lo (mesmo que esteja vazio).

Há também um caso em que você pode realmente usar um arquivo __init__.py:

Imagine que você tinha a seguinte estrutura de arquivo:

main_methods 
    |- methods.py

E methods.py continha o seguinte:

def foo():
    return 'foo'

Para usar foo() você precisaria de um dos seguintes:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

Talvez você precisa (ou quer) para manter methods.py dentro main_methods (a autonomia / dependências, por exemplo), mas você só quer main_methods importação.


Se você mudou o nome de methods.py para __init__.py então você poderia usar foo() por apenas main_methods importação:

import main_methods
print(main_methods.foo()) # Prints 'foo'

Isso funciona porque __init__.py é tratado como parte do pacote.


Alguns pacotes Python realmente fazer isso. Um exemplo é com JSON , onde executando import json é realmente importar __init__.py do pacote json ( ver a estrutura arquivo de pacote aqui ):

Código Fonte: Lib/json/__init__.py

__init__.py irá tratar o diretório é como um módulo carregável.

Para as pessoas que preferem leitura de código, eu coloquei Two-Bit comentário do alquimista aqui.

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

Ele facilita a importação de outros arquivos python. Quando você colocou esse arquivo em um diretório (coisas digamos) contendo outros arquivos py, então você pode fazer algo como stuff.other importação.

root\
    stuff\
         other.py

    morestuff\
         another.py

Sem esta __init__.py no interior do material de diretório, você não poderia importar other.py, porque Python não sabe onde o código fonte para material é e incapaz de reconhecê-lo como um pacote.

Um arquivo __init__.py faz importações fácil. Quando um __init__.py está presente dentro de um pacote, função a() podem ser importados de b.py arquivo assim:

from b import a

Sem ele, no entanto, você não pode importar diretamente. Você tem que alterar o caminho do sistema:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top