Respostas:
Costumava ser uma parte necessária de um pacote ( antigo "pacote regular" anterior à 3.3 , e não mais recente "pacote de namespace" 3.3+ mais recente ).
Python define dois tipos de pacotes, pacotes regulares e pacotes de namespace. Pacotes regulares são pacotes tradicionais, como existiam no Python 3.2 e versões anteriores. Um pacote regular é normalmente implementado como um diretório que contém um
__init__.py
arquivo. Quando um pacote regular é importado, esse__init__.py
arquivo é executado implicitamente e os objetos que ele define são vinculados aos nomes no espaço para nome do pacote. O__init__.py
arquivo pode conter o mesmo código Python que qualquer outro módulo pode conter, e o Python adicionará alguns atributos adicionais ao módulo quando ele for importado.
Mas basta clicar no link, ele contém um exemplo, mais informações e uma explicação dos pacotes de namespace, o tipo de pacote sem __init__.py
.
sys.path.insert(0, '/path/to/datetime')
, substituindo esse caminho pelo caminho para o diretório que você acabou de criar. Agora tente algo parecido from datetime import datetime;datetime.now()
. Você deve obter um AttributeError (porque está importando seu arquivo em branco agora). Se você repetisse essas etapas sem criar o arquivo init em branco, isso não aconteceria. Isso é o que se pretende impedir.
from datetime import datetime
sem erros. Isso é bom desde a versão 2.3!
builtins
lista funções e classes internas , não módulos internos (cf. docs.python.org/3/tutorial/modules.html#the-dir-function ). Se você deseja listar os módulos internos , faça import sys; print(sys.builtin_module_names)
(cf. docs.python.org/3/library/sys.html#sys.builtin_module_names ).
Os arquivos nomeados __init__.py
são usados para marcar diretórios no disco como diretórios de pacotes Python. Se você tiver os arquivos
mydir/spam/__init__.py
mydir/spam/module.py
e mydir
está no seu caminho, você pode importar o código module.py
como
import spam.module
ou
from spam import module
Se você remover o __init__.py
arquivo, o Python não procurará mais submódulos dentro desse diretório; portanto, as tentativas de importar o módulo falharão.
O __init__.py
arquivo geralmente está vazio, mas pode ser usado para exportar partes selecionadas do pacote com um nome mais conveniente, manter funções de conveniência etc. etc. Dado o exemplo acima, o conteúdo do módulo init pode ser acessado como
import spam
com base nisso
__init__.py
foi necessário no Python 2.X e ainda é necessário no Python 2.7.12 (eu testei), mas não é mais necessário (supostamente) do Python 3.3 em diante e não é necessário no Python 3.4.3 (I testado). Consulte stackoverflow.com/questions/37139786 para obter mais detalhes.
__init__.py
.
setup.py
e usar find_packages()
, é necessário ter __init__.py
em todos os diretórios. Veja stackoverflow.com/a/56277323/7127824
Além de rotular um diretório como um pacote Python e definir __all__
, __init__.py
permite definir qualquer variável no nível do pacote. Isso geralmente é conveniente se um pacote definir algo que será importado com frequência, de maneira semelhante à API. Esse padrão promove a aderência à filosofia "plana é melhor do que aninhada".
Aqui está um exemplo de um dos meus projetos, no qual eu frequentemente importo uma sessionmaker
chamada Session
para interagir com meu banco de dados. Eu escrevi um pacote "database" com alguns módulos:
database/
__init__.py
schema.py
insertions.py
queries.py
My __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)
Como defino Session
aqui, posso iniciar uma nova sessão usando a sintaxe abaixo. Esse código seria o mesmo executado dentro ou fora do diretório do pacote "database".
from database import Session
session = Session()
Obviamente, essa é uma pequena 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()
Existe um tópico reddit bastante interessante que cobre os usos apropriados __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 __init__.py
arquivos devem ser muito finos para evitar violar a filosofia "explícito é melhor que implícito".
engine
, sessionmaker
, create_engine
, E os
podem também ser importados de database
agora ... parece que você fez uma confusão de que namespace.
__all__ = [...]
para limitar o que é importado import *
. Além disso, sim, você fica com um namespace de nível superior confuso.
Existem 2 razões principais para __init__.py
Por conveniência: os outros usuários não precisarão conhecer a localização exata de suas funções na 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
outras pessoas podem chamar add () por
from your_package import add
sem saber file1, como
from your_package.file1 import add
Se você deseja que algo seja inicializado; por exemplo, log (que deve ser colocado no nível superior):
import logging.config
logging.config.dictConfig(Your_logging_config)
__init__.py
pode ser útil algumas vezes, mas nem sempre.
O __init__.py
arquivo faz o Python tratar os diretórios que o contêm como módulos.
Além disso, este é o primeiro arquivo a ser carregado em um módulo, portanto, você pode usá-lo para executar o código que deseja executar cada vez que um módulo é carregado ou especificar os submódulos a serem exportados.
Desde o Python 3.3, __init__.py
não é mais necessário definir diretórios como pacotes Python importáveis.
Verifique PEP 420: Pacotes implícitos de espaço para nome :
Suporte nativo para diretórios de pacotes que não exigem
__init__.py
arquivos de marcadores e podem se estender automaticamente a vários segmentos de caminho (inspirados em várias abordagens de terceiros para pacotes de namespace, conforme descrito no 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/
Is __init__. py não é necessário para pacotes em Python 3?
No Python, a definição de pacote é muito simples. Como Java, a estrutura hierárquica e a estrutura de diretórios são as mesmas. Mas você tem que ter __init__.py
em um pacote. Vou explicar o __init__.py
arquivo 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, enquanto existir. Indica que o diretório deve ser considerado como um pacote. Claro, __init__.py
também pode definir o conteúdo apropriado.
Se adicionarmos uma função no module_n1:
def function_X():
print "function_X in module_n1"
return
Depois de correr:
>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()
function_X in module_n1
Em seguida, seguimos o pacote de hierarquia e chamamos module_n1 a função. Podemos usar __init__.py
no subPackage_b assim:
__all__ = ['module_n2', 'module_n3']
Depois de correr:
>>>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
Portanto, usando a importação *, o pacote do módulo está sujeito ao __init__.py
conteúdo.
from package_x.subPackage_b.module_n1 import function_X
Embora o Python funcione sem um __init__.py
arquivo, você ainda deve incluir um.
Ele especifica que um pacote deve ser tratado como um módulo; portanto, inclua-o (mesmo que esteja vazio).
Também existe um caso em que você pode realmente usar um __init__.py
arquivo:
Imagine que você tivesse a seguinte estrutura de arquivos:
main_methods
|- methods.py
E methods.py
continha isso:
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ê precise (ou queira) manter methods.py
dentro main_methods
(tempos de execução / dependências, por exemplo), mas você só deseja importar main_methods
.
Se você mudou o nome de methods.py
para, __init__.py
então você pode usarfoo()
apenas importando main_methods
:
import main_methods
print(main_methods.foo()) # Prints 'foo'
Isso funciona porque __init__.py
é tratado como parte do pacote.
Alguns pacotes Python realmente fazem isso. Um exemplo é com JSON , em que a execução import json
é realmente importada __init__.py
do json
pacote ( consulte a estrutura do arquivo do pacote aqui ):
Código fonte:
Lib/json/__init__.py
__init__.py
tratará o diretório em que está como um módulo carregável.
Para quem prefere ler código, coloquei o comentário do Alquimista de dois bits 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
>>>
Facilita a importação de outros arquivos python. Quando você colocou esse arquivo em um diretório (digamos, stuff) contendo outros arquivos py, você pode fazer algo como importar coisas.outros.
root\
stuff\
other.py
morestuff\
another.py
Sem isso __init__.py
dentro do diretório, você não poderia importar other.py, porque o Python não sabe onde está o código-fonte e não consegue reconhecê-lo como um pacote.
Um __init__.py
arquivo facilita as importações. Quando um __init__.py
está presente em um pacote, a função a()
pode ser importada do arquivo da seguinte b.py
maneira:
from b import a
Sem ele, no entanto, você não pode importar diretamente. Você precisa alterar o caminho do sistema:
import sys
sys.path.insert(0, 'path/to/b.py')
from b import a