2009-12-22 3 views
148

Il mio pacchetto ha la seguente struttura:Come faccio a scrivere buoni corrette file __init__.py/pacchetto

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 
    ... 

io non sono sicuro di come i file __init__.py devono essere scritti in modo corretto.
Il __init__.py #1 assomiglia:

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

Ma come per esempio __init__.py #2 assomigliare? Il mio è:

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

Quando dovrebbe essere __all__ utilizzato?

+0

Tenere presente tuttavia che l'utilizzo dell'importazione * nel codice è in genere una pratica molto scorretta e dovrebbe essere evitato se possibile. Ci sono pochissimi buoni casi d'uso per questo, ma sono davvero rari. – Mayou36

risposta

116

__all__ è molto buona - aiuta dichiarazioni guida di importazione senza moduli importando automaticamente http://docs.python.org/tutorial/modules.html#importing-from-a-package

usando __all__ e import * è ridondante, è necessario solo __all__

credo che uno dei più potenti motivi per utilizzare import * in un __init__.py per importare i pacchetti deve essere in grado di refactoring uno script che è cresciuto in più script senza rompere un'applicazione esistente. Ma se stai progettando un pacchetto dall'inizio. Penso che sia meglio lasciare i file __init__.py vuoti.

ad esempio:

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

quindi l'applicazione cresce e ora è un'intera cartella

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

allora lo script di init può dire

__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 

in modo che uno script scritto per effettuare le seguenti operazioni non si interrompe durante la modifica:

from foo import fooFactory, tallFoo, shortFoo 
+2

Ero molto confuso riguardo a "__all__" e all'importazione riga per riga. Il tuo esempio è molto illuminante. – Junchen

98

I miei file __init__.py sono vuoti il ​​più delle volte. In particolare, non ho mai un __init__.py__init__.py - se "importare il pacchetto" significa ottenere tutti i tipi di classi, funzioni ecc definite direttamente come parte del pacchetto, quindi vorrei copiare lessicamente il contenuto di blah.py nel pacchetto __init__.py invece e rimuovere blah.py (la moltiplicazione dei file sorgente non va bene qui).

Se si insiste a supportare gli idiomi import * (eek), quindi utilizzare __all__ (con come minuscolo un elenco di nomi che si può portare ad avere in esso) può aiutare per il controllo dei danni. In generale, gli spazi dei nomi e le importazioni espliciti sono buoni cose, e ho forti suggeriscono riconsiderando qualsiasi approccio basato sulla sistematica bypassando uno o entrambi i concetti -!)

+9

Personalmente, preferisco mantenere le cose separate e quindi importare *. Il motivo è che, nonostante la piegatura e le cose, continuo a odiare i file contenenti troppe classi, anche se correlate. –

+4

@stefano pensa a un grande quadro.se usa 'import *' devi accettare incondizionatamente tutto il framework in tutte le sue funzioni, anche quelle che non userai mai. mantenere '__init __. py' vuoto ti offre più possibilità di una semplice semantica tutto o niente. pensa a contorto. –

+0

se lo si mantiene vuoto, anche dopo l'importazione di mobilescouter, non si può ancora utilizzare mobilescouter.mapper o mobilescouter.vehicle o mobilescouter.whatever. non è importare mobilescouter.A, mobilescouter.B ..... troppo prolisso? – sunqiang