Respostas:
É uma lista de objetos públicos desse módulo, conforme interpretado por import *
. Ele substitui o padrão de ocultar tudo o que começa com um sublinhado.
import *
(como por exemplo tk
). Uma boa dica, se esse for o caso, é a presença __all__
ou nomes começando com sublinhado no código do módulo.
tk
fosse lançado hoje (ou mesmo em 2012), a prática recomendada seria o uso from tk import *
. Eu acho que a prática é aceita devido à inércia, não ao design intencional.
Vinculado a, mas não mencionado explicitamente aqui, é exatamente quando __all__
é usado. É uma lista de cadeias que definem quais símbolos em um módulo serão exportados quando from <module> import *
usados no módulo.
Por exemplo, o código a seguir em um foo.py
exporta explicitamente os símbolos bar
e baz
:
__all__ = ['bar', 'baz']
waz = 5
bar = 10
def baz(): return 'baz'
Esses símbolos podem ser importados da seguinte maneira:
from foo import *
print(bar)
print(baz)
# The following will trigger an exception, as "waz" is not exported by the module
print(waz)
Se o __all__
comentário acima for comentado, esse código será executado até a conclusão, pois o comportamento padrão de import *
é importar todos os símbolos que não começam com um sublinhado, do espaço de nome fornecido.
Referência: https://docs.python.org/tutorial/modules.html#importing-from-a-package
NOTA: __all__
afeta from <module> import *
apenas o comportamento. Os membros que não são mencionados __all__
ainda estão acessíveis de fora do módulo e podem ser importados com from <module> import <member>
.
print(baz())
?
print(baz)
imprime algo como <function baz at 0x7f32bc363c10>
enquanto print(baz())
imprimebaz
Explique __all__ em Python?
Eu continuo vendo a variável
__all__
definida em__init__.py
arquivos diferentes .O que isso faz?
__all__
faz?Ele declara os nomes semanticamente "públicos" de um módulo. Se houver um nome __all__
, espera-se que os usuários o usem e eles podem ter a expectativa de que isso não será alterado.
Também terá efeitos programáticos:
import *
__all__
em um módulo, por exemplo module.py
:
__all__ = ['foo', 'Bar']
significa que, quando você import *
do módulo, apenas os nomes no __all__
são importados:
from module import * # imports foo and Bar
As ferramentas de preenchimento automático de documentação e código também podem (na verdade, devem) inspecionar __all__
para determinar quais nomes serão exibidos como disponíveis em um módulo.
__init__.py
transforma um diretório em um pacote PythonDos documentos :
Os
__init__.py
arquivos são necessários para fazer o Python tratar os diretórios como contendo pacotes; isso é feito para impedir que diretórios com um nome comum, como string, ocultem acidentalmente módulos válidos que ocorrem posteriormente no caminho de pesquisa do módulo.No caso mais simples,
__init__.py
pode ser apenas um arquivo vazio, mas também pode executar o código de inicialização do pacote ou definir a__all__
variável.
Assim, o __init__.py
pode declarar o __all__
para um pacote .
Um pacote geralmente é composto de módulos que podem importar um ao outro, mas necessariamente vinculados a um __init__.py
arquivo. Esse arquivo é o que torna o diretório um pacote Python real. Por exemplo, digamos que você tenha os seguintes arquivos em um pacote:
package
├── __init__.py
├── module_1.py
└── module_2.py
Vamos criar esses arquivos com o Python para que você possa acompanhar - você pode colar o seguinte em um shell do Python 3:
from pathlib import Path
package = Path('package')
package.mkdir()
(package / '__init__.py').write_text("""
from .module_1 import *
from .module_2 import *
""")
package_module_1 = package / 'module_1.py'
package_module_1.write_text("""
__all__ = ['foo']
imp_detail1 = imp_detail2 = imp_detail3 = None
def foo(): pass
""")
package_module_2 = package / 'module_2.py'
package_module_2.write_text("""
__all__ = ['Bar']
imp_detail1 = imp_detail2 = imp_detail3 = None
class Bar: pass
""")
E agora você apresentou uma API completa que outra pessoa pode usar quando importar seu pacote, assim:
import package
package.foo()
package.Bar()
E o pacote não terá todos os outros detalhes de implementação que você usou ao criar seus módulos sobrecarregando o package
espaço para nome.
__all__
no __init__.py
Depois de mais trabalho, talvez você tenha decidido que os módulos são muito grandes (como milhares de linhas?) E precisam ser divididos. Então você faz o seguinte:
package
├── __init__.py
├── module_1
│ ├── foo_implementation.py
│ └── __init__.py
└── module_2
├── Bar_implementation.py
└── __init__.py
Primeiro, crie os diretórios do subpacote com os mesmos nomes dos módulos:
subpackage_1 = package / 'module_1'
subpackage_1.mkdir()
subpackage_2 = package / 'module_2'
subpackage_2.mkdir()
Mova as implementações:
package_module_1.rename(subpackage_1 / 'foo_implementation.py')
package_module_2.rename(subpackage_2 / 'Bar_implementation.py')
crie __init__.py
s para os subpacotes que declaram o __all__
para cada um:
(subpackage_1 / '__init__.py').write_text("""
from .foo_implementation import *
__all__ = ['foo']
""")
(subpackage_2 / '__init__.py').write_text("""
from .Bar_implementation import *
__all__ = ['Bar']
""")
E agora você ainda tem a API provisionada no nível do pacote:
>>> import package
>>> package.foo()
>>> package.Bar()
<package.module_2.Bar_implementation.Bar object at 0x7f0c2349d210>
E você pode facilmente adicionar à sua API coisas que você pode gerenciar no nível do subpacote, em vez do nível do módulo do subpacote. Se você deseja adicionar um novo nome à API, basta atualizar o __init__.py
, por exemplo, no module_2:
from .Bar_implementation import *
from .Baz_implementation import *
__all__ = ['Bar', 'Baz']
E se você não estiver pronto para publicar Baz
na API de nível superior, em seu nível superior, __init__.py
você poderá ter:
from .module_1 import * # also constrained by __all__'s
from .module_2 import * # in the __init__.py's
__all__ = ['foo', 'Bar'] # further constraining the names advertised
e se seus usuários estiverem cientes da disponibilidade de Baz
, eles poderão usá-lo:
import package
package.Baz()
mas se eles não souberem disso, outras ferramentas (como pydoc ) não os informarão.
Mais tarde, você pode alterar isso quando Baz
estiver pronto para o horário nobre:
from .module_1 import *
from .module_2 import *
__all__ = ['foo', 'Bar', 'Baz']
_
versus __all__
:Por padrão, o Python exportará todos os nomes que não começam com um _
. Você certamente poderia confiar nesse mecanismo. Alguns pacotes na biblioteca padrão do Python, de fato, não contar com isso, mas a fazê-lo, eles apelido suas importações, por exemplo, em ctypes/__init__.py
:
import os as _os, sys as _sys
O uso da _
convenção pode ser mais elegante, pois remove a redundância de nomear os nomes novamente. Mas adiciona a redundância para importações (se houver muitas) e é fácil esquecer de fazer isso de forma consistente - e a última coisa que você quer é ter que suportar indefinidamente algo que você pretendia ser apenas um detalhe de implementação, apenas porque você esqueceu de prefixar um _
ao nomear uma função.
Eu pessoalmente escrevi um __all__
ciclo de vida de desenvolvimento no início de módulos para que outras pessoas que possam usar meu código saibam o que devem usar e não usar.
A maioria dos pacotes na biblioteca padrão também usa __all__
.
__all__
faz sentidoFaz sentido seguir a _
convenção de prefixo em vez de __all__
:
export
decoradorA desvantagem de usar __all__
é que você precisa escrever os nomes das funções e classes que estão sendo exportadas duas vezes - e as informações são mantidas separadas das definições. Nós poderia usar um decorador para resolver este problema.
Tive a ideia de um decorador de exportação desse discurso de David Beazley sobre embalagem. Essa implementação parece funcionar bem no importador tradicional do CPython. Se você tiver um sistema ou gancho de importação especial, eu não garanto, mas se você adotá-lo, é bastante trivial voltar atrás - você só precisará adicionar manualmente os nomes novamente ao diretório__all__
Portanto, em uma biblioteca de utilidades, por exemplo, você definiria o decorador:
import sys
def export(fn):
mod = sys.modules[fn.__module__]
if hasattr(mod, '__all__'):
mod.__all__.append(fn.__name__)
else:
mod.__all__ = [fn.__name__]
return fn
e então, onde você definiria um __all__
, faça o seguinte:
$ cat > main.py
from lib import export
__all__ = [] # optional - we create a list if __all__ is not there.
@export
def foo(): pass
@export
def bar():
'bar'
def main():
print('main')
if __name__ == '__main__':
main()
E isso funciona bem, seja executado como principal ou importado por outra função.
$ cat > run.py
import main
main.main()
$ python run.py
main
E o provisionamento da API import *
também funcionará:
$ cat > run.py
from main import *
foo()
bar()
main() # expected to error here, not exported
$ python run.py
Traceback (most recent call last):
File "run.py", line 4, in <module>
main() # expected to error here, not exported
NameError: name 'main' is not defined
@export
decorador.
__init__.py
eo uso de__all__
__all__
está correto.
__all__
também - mas eu diria que você tem uma API instável ... Isso seria algo para se ter alguns testes de aceitação abrangentes.
module_1
e module_2
; é OK para incluir uma explícita del module_1
em __init__.py
? Estou errado em pensar que isso vale a pena?
Estou apenas adicionando isso para ser preciso:
Todas as outras respostas se referem aos módulos . A pergunta original mencionada explicitamente __all__
nos __init__.py
arquivos, portanto, trata-se de pacotes python .
Geralmente, __all__
só entra em jogo quando a from xxx import *
variante da import
declaração é usada. Isso se aplica aos pacotes e aos módulos.
O comportamento dos módulos é explicado nas outras respostas. O comportamento exato dos pacotes é descrito aqui em detalhes.
Em resumo, __all__
no nível do pacote faz aproximadamente a mesma coisa que para os módulos, exceto que trata dos módulos dentro do pacote (em contraste com a especificação de nomes dentro do módulo ). Assim, __all__
especifica todos os módulos que devem ser carregados e importados para o espaço para nome atual quando usamos from package import *
.
A grande diferença é que, quando você omitir a declaração de __all__
em um pacote __init__.py
, a instrução from package import *
não importará nada (com exceções explicadas na documentação, consulte o link acima).
Por outro lado, se você omitir __all__
um módulo, a "importação com estrela" importará todos os nomes (não começando com um sublinhado) definidos no módulo.
from package import *
ainda importará tudo o que estiver definido __init__.py
, mesmo que não exista all
. A diferença importante é que, sem __all__
ele, não importará automaticamente nenhum módulo definido no diretório do pacote.
Também muda o que o pydoc mostrará:
module1.py
a = "A"
b = "B"
c = "C"
module2.py
__all__ = ['a', 'b']
a = "A"
b = "B"
c = "C"
$ pydoc module1
Ajuda no módulo module1: NOME Módulo 1 ARQUIVO module1.py DADOS a = 'A' b = 'B' c = 'C'
$ pydoc module2
Ajuda no módulo module2: NOME module2 ARQUIVO module2.py DADOS __all__ = ['a', 'b'] a = 'A' b = 'B'
Declaro __all__
em todos os meus módulos, além de sublinhar os detalhes internos, que realmente ajudam ao usar coisas que você nunca usou antes em sessões de intérpretes ao vivo.
__all__
personaliza *
emfrom <module> import *
__all__
personaliza *
emfrom <package> import *
Um módulo é um .py
arquivo que deve ser importado.
Um pacote é um diretório com um __init__.py
arquivo. Um pacote geralmente contém módulos.
""" cheese.py - an example module """
__all__ = ['swiss', 'cheddar']
swiss = 4.99
cheddar = 3.99
gouda = 10.99
__all__
permite que os humanos conheçam os recursos "públicos" de um módulo . [ @AaronHall ] Além disso, o pydoc os reconhece. [ @Longpoke ]
Veja como swiss
e cheddar
são trazidos para o espaço para nome local, mas não gouda
:
>>> from cheese import *
>>> swiss, cheddar
(4.99, 3.99)
>>> gouda
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'gouda' is not defined
Sem __all__
, qualquer símbolo (que não comece com um sublinhado) estaria disponível.
*
não são afetadas por__all__
>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)
>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)
>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)
No __init__.py
arquivo de um pacote, __all__
há uma lista de cadeias com os nomes de módulos públicos ou outros objetos. Esses recursos estão disponíveis para importações de caracteres curinga. Como nos módulos, __all__
personaliza a *
importação de curingas do pacote. [ @MartinStettner ]
Aqui está um trecho do Python MySQL Connector __init__.py
:
__all__ = [
'MySQLConnection', 'Connect', 'custom_error_exception',
# Some useful constants
'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
'HAVE_CEXT',
# Error handling
'Error', 'Warning',
...etc...
]
O caso padrão, asterisco sem no __all__
para um pacote , é complicado, porque o comportamento óbvio seria caro: usar o sistema de arquivos para procurar todos os módulos no pacote. Em vez disso, na minha leitura dos documentos, apenas os objetos definidos em __init__.py
são importados:
Se
__all__
não for definido, a declaraçãofrom sound.effects import *
não não importar todos os submódulos do pacotesound.effects
para o namespace atual; ele garante apenas que o pacotesound.effects
foi importado (possivelmente executando qualquer código de inicialização__init__.py
) e depois importa os nomes definidos no pacote. Isso inclui qualquer nome definido (e sub-módulos explicitamente carregados) por__init__.py
. Ele também inclui quaisquer submódulos do pacote que foram explicitamente carregados por instruções de importação anteriores.
As importações de caracteres curinga ... devem ser evitadas, pois confundem os leitores e muitas ferramentas automatizadas.
[ PEP 8 , @ToolmakerSteve]
from <package> import *
sem __all__
em __init__.py
que está não importar qualquer um dos módulos .
__init__.py
fosse um módulo . Mas não tenho certeza se isso é exato ou, em particular, se objetos com prefixo sublinhado são excluídos. Além disso, separei mais claramente as seções sobre MÓDULOS e PACOTES. Seus pensamentos?
De (An Unofficial) Python Wiki Referência :
Os nomes públicos definidos por um módulo são determinados verificando o espaço de nomes do módulo para uma variável denominada
__all__
; se definido, deve ser uma sequência de cadeias que são nomes definidos ou importados por esse módulo. Os nomes dados__all__
são todos considerados públicos e devem existir. Se__all__
não estiver definido, o conjunto de nomes públicos inclui todos os nomes encontrados no espaço para nome do módulo que não começam com um caractere sublinhado ("_").__all__
deve conter toda a API pública. Destina-se a evitar a exportação acidental de itens que não fazem parte da API (como módulos de biblioteca que foram importados e usados dentro do módulo).
__all__
é usado para documentar a API pública de um módulo Python. Embora seja opcional, __all__
deve ser usado.
Aqui está o trecho relevante da referência da linguagem Python :
Os nomes públicos definidos por um módulo são determinados verificando o espaço de nomes do módulo para uma variável denominada
__all__
; se definido, deve ser uma sequência de cadeias que são nomes definidos ou importados por esse módulo. Os nomes dados__all__
são todos considerados públicos e devem existir. Se__all__
não estiver definido, o conjunto de nomes públicos inclui todos os nomes encontrados no espaço para nome do módulo que não começam com um caractere sublinhado ('_').__all__
deve conter toda a API pública. Destina-se a evitar a exportação acidental de itens que não fazem parte da API (como módulos de biblioteca que foram importados e usados dentro do módulo).
O PEP 8 usa palavras semelhantes, embora também deixe claro que nomes importados não fazem parte da API pública quando __all__
estão ausentes:
Para oferecer melhor suporte à introspecção, os módulos devem declarar explicitamente os nomes em sua API pública usando o
__all__
atributo A configuração__all__
para uma lista vazia indica que o módulo não possui API pública.[...]
Os nomes importados devem sempre ser considerados um detalhe de implementação. Outros módulos não devem confiar no acesso indireto a esses nomes importados, a menos que sejam uma parte explicitamente documentada da API do módulo que contém, como
os.path
um__init__
módulo de um pacote que exponha a funcionalidade dos submódulos.
Além disso, como indicado em outras respostas, __all__
é usado para ativar a importação de curingas para pacotes :
A instrução de importação usa a seguinte convenção: se o
__init__.py
código de um pacote definir uma lista denominada__all__
, será considerada a lista de nomes de módulos que devem ser importados quandofrom package import *
encontrados.
__all__
afeta from <module> import *
declarações.
Considere este exemplo:
foo
├── bar.py
└── __init__.py
Em foo/__init__.py
:
(Implícito) Se não definirmos __all__
, from foo import *
importará apenas os nomes definidos em foo/__init__.py
.
(Explícito) Se definirmos __all__ = []
, from foo import *
não importará nada.
(Explícito) Se definirmos __all__ = [ <name1>, ... ]
, from foo import *
importará apenas esses nomes.
Observe que, no caso implícito, o python não importará nomes começando com _
. No entanto, você pode forçar a importação desses nomes usando __all__
.
Você pode visualizar o documento Python aqui .
__all__
afeta como from foo import *
funciona.
O código que está dentro do corpo de um módulo (mas não no corpo de uma função ou classe) pode usar um asterisco ( *
) em uma from
instrução:
from foo import *
As *
solicitações para que todos os atributos do módulo foo
(exceto aqueles que começam com sublinhados) sejam vinculados como variáveis globais no módulo de importação. Quando foo
tem um atributo __all__
, o valor do atributo é a lista dos nomes que estão vinculados por esse tipo de from
instrução.
Se foo
é um pacote e __init__.py
define uma lista com nome __all__
, é considerada a lista de nomes de sub-módulos que devem ser importados quando from foo import *
encontrados. Se __all__
não estiver definido, a instrução from foo import *
importará quaisquer nomes definidos no pacote. Isso inclui qualquer nome definido (e sub-módulos explicitamente carregados) por __init__.py
.
Observe que __all__
não precisa ser uma lista. Conforme a documentação na import
instrução , se definida, __all__
deve haver uma sequência de seqüências de caracteres que são nomes definidos ou importados pelo módulo. Portanto, você também pode usar uma tupla para economizar alguns ciclos de memória e CPU. Apenas não esqueça uma vírgula, caso o módulo defina um único nome público:
__all__ = ('some_name',)
Veja também Por que "import *" é ruim?
Isso é definido no PEP8 aqui :
Nomes de variáveis globais
(Vamos torcer para que essas variáveis sejam usadas apenas dentro de um módulo.) As convenções são praticamente as mesmas das funções.
Os módulos projetados para uso via
from M import *
devem usar o__all__
mecanismo para impedir a exportação de globais, ou usar a convenção anterior de prefixar esses globais com um sublinhado (o que você pode querer fazer para indicar que esses globais são "módulos não públicos").
O PEP8 fornece convenções de codificação para o código Python, que compreende a biblioteca padrão na distribuição principal do Python. Quanto mais você segue isso, mais perto está da intenção original.
__all__
se__all__
estiver presente, não são exatamente ocultos; eles podem ser vistos e acessados perfeitamente normalmente, se você souber o nome deles. É apenas no caso de uma "importação *", que não é recomendada de qualquer maneira, que a distinção tenha algum peso.