Como eu escrevo arquivos __init__.py de pacote corretos / corretos


188

Meu pacote tem a seguinte estrutura:

mobilescouter/
    __init__.py #1
    mapper/
        __init__.py  #2
        lxml/
            __init__.py #3
            vehiclemapper.py
            vehiclefeaturemapper.py
            vehiclefeaturesetmapper.py
        ...
        basemapper.py
   vehicle/
        __init__.py #4
        vehicle.py
        vehiclefeature.py
        vehiclefeaturemapper.py
   ...

Não tenho certeza de como os __init__.pyarquivos devem ser escritos corretamente.
Os __init__.py #1parece:

__all__ = ['mapper', 'vehicle']
import mapper
import vehicle

Mas como deve ser, por exemplo __init__.py #2? O meu é:

__all__ = ['basemapper', 'lxml']
from basemaper import *
import lxml

Quando deve ser __all__usado?


3
Esteja ciente de que o uso de importação * no código geralmente é uma prática muito ruim e deve ser evitado, se possível. Existem muito poucos casos de uso bons para isso, mas eles são realmente raros.
precisa saber é o seguinte

PSA: Se você estiver interessado em aprender como escrever pacotes de namespace bom (o novo tipo de pacote), confira este pacote de exemplo: github.com/pypa/sample-namespace-packages
Kyle

Respostas:


146

__all__é muito bom - ajuda a orientar as instruções de importação sem importar automaticamente os módulos http://docs.python.org/tutorial/modules.html#importing-from-a-package

usando __all__e import *é redundante, apenas __all__é necessário

Eu acho que uma das razões mais poderosas para usar import *em um __init__.pypacote para importar é poder refatorar um script que cresceu em vários scripts sem quebrar um aplicativo existente. Mas se você estiver projetando um pacote desde o início. Eu acho que é melhor deixar os __init__.pyarquivos vazios.

por exemplo:

foo.py - contains classes related to foo such as fooFactory, tallFoo, shortFoo

então o aplicativo cresce e agora é uma pasta inteira

foo/
    __init__.py
    foofactories.py
    tallFoos.py
    shortfoos.py
    mediumfoos.py
    santaslittlehelperfoo.py
    superawsomefoo.py
    anotherfoo.py

então o script init pode dizer

__all__ = ['foofactories', 'tallFoos', 'shortfoos', 'medumfoos',
           'santaslittlehelperfoo', 'superawsomefoo', 'anotherfoo']
# deprecated to keep older scripts who import this from breaking
from foo.foofactories import fooFactory
from foo.tallfoos import tallFoo
from foo.shortfoos import shortFoo

para que um script escrito para fazer o seguinte não seja interrompido durante a alteração:

from foo import fooFactory, tallFoo, shortFoo

3
Fiquei muito confuso sobre ' tudo ' e linha por linha de importação. Seu exemplo é muito esclarecedor.
Junchen

2
Estou confuso com " __all__e import *é redundante", __all__é usado pelo consumidor do módulo, e from foo import *é usado pelo próprio módulo para usar outros ....
Nick T

using __all__ and import * is redundant, only __all__ is needed Como são aqueles redundantes? Eles fazem coisas diferentes.
endolith

113

Meus próprios __init__.pyarquivos estão vazios com mais frequência do que não. Em particular, eu nunca tenho um from blah import *como parte __init__.py- se "importar o pacote" significa obter todos os tipos de classes, funções etc definidas diretamente como parte do pacote, então eu copiava lexicamente o conteúdo do conteúdo blah.pypara o pacote __init__.pye o removia blah.py( a multiplicação dos arquivos de origem não serve aqui).

Se você insistir em apoiar os import *idiomas (eek), usar __all__(com uma lista tão minúscula de nomes quanto possível) pode ajudar a controlar os danos. Em geral, namespaces e importações explícitas são boas , e eu sugiro reconsiderar qualquer abordagem baseada em ignorar sistematicamente um ou ambos os conceitos! -)


9
Pessoalmente, prefiro manter as coisas separadas e depois importar *. A razão é que, apesar das dobras e outras coisas, eu ainda odeio procurar arquivos contendo muitas classes, mesmo se relacionadas.
23909 Stefano Borini

5
@stefano pense em uma grande estrutura. se ele usar, import *você deve aceitar incondicionalmente toda a estrutura em si, inclusive os recursos que você nunca usará. manter-se __init__.pyvazio oferece mais chances do que apenas a semântica de tudo ou nada. pense torcido.
mg.

se mantê-lo vazio, mesmo após a importação do mobilescouter, ainda não é possível usar mobilescouter.mapper ou mobilescouter.vehicle ou mobilescouter.whatever. não é import mobilescouter.A, mobilescouter.B ..... muito detalhado?
22909 sunqiang

6
@ Sunqiang isso é pessoal, mas acho que não. from mobilescouter import A, Bé apenas uma linha de código e você não tem um projeto com 666 classes e cada um com seu próprio arquivo, certo? se você tiver dois ou mais import *códigos, estará preenchendo o espaço para nome com um possível lixo e rapidamente esquecerá de onde Avem. E se um pacote superior fizer o mesmo? você está pegando todos os subpacotes e subpacotes. como o zen do python diz, explícito é melhor que implícito.
mg.

1
@mg, se houver uma linha "import A, B" no arquivo init .py, posso chamar o A (ou B) com a sintaxe: mobilescouter.A; se usarmos "da importação de mobilescouter A, B", será apenas A. algo. em algum momento, apenas nesta linha, não me lembro de A é um subpacak do mobilescouter, e acho que isso contribui para a poluição do namespace (embora seja muito melhor que "" da importação do mobilescouter * ". Ainda prefiro" import pkgname " . a interface pública uniforme de modo de inicialização .py fazer as coisas de importação sub_pkgname.
sunqiang

1

Você __init__.pydeve ter uma doutrina .

Embora toda a funcionalidade seja implementada em módulos e subpacotes, a documentação do pacote é o local para documentar por onde começar. Por exemplo, considere o pacote pythonemail . A documentação do pacote é uma introdução que descreve a finalidade, os antecedentes e como os vários componentes do pacote funcionam juntos. Se você gerar automaticamente a documentação a partir de docstrings usando sphinx ou outro pacote, a docstring do pacote é exatamente o lugar certo para descrever essa introdução.

Para qualquer outro conteúdo, veja as excelentes respostas de firecrow e Alex Martelli .


O valor real __init__.pydo emailpacote segue esta diretriz? Eu vejo uma única linha de doutrina que não ajuda muito a explicar "como os vários componentes do pacote funcionam juntos".
Gertlex

@ Gertlex Talvez apenas na documentação da web.
gerrit 11/11/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.