¿Cómo escribo archivos de paquete __init__.py buenos / correctos

188

Mi paquete tiene la siguiente estructura:

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

No estoy seguro de cómo se __init__.pydeben escribir correctamente los archivos.
El se __init__.py #1parece a:

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

Pero, ¿cómo debería ser, por ejemplo __init__.py #2? El mio es:

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

¿Cuándo se debe __all__usar?

Marten Bauer
fuente
3
Sin embargo, tenga en cuenta que usar import * en el código generalmente es una práctica muy mala y debe evitarse si es posible. Hay muy pocos casos de buen uso para esto, pero son realmente raros.
Mayou36
PSA: si está interesado en aprender a escribir buenos paquetes de espacio de nombres (el nuevo tipo de paquete), consulte este paquete de ejemplo: github.com/pypa/sample-namespace-packages
Kyle

Respuestas:

146

__all__es muy bueno: ayuda a guiar las declaraciones de importación sin importar automáticamente los módulos http://docs.python.org/tutorial/modules.html#importing-from-a-package

usando __all__y import *es redundante, solo __all__es necesario

Creo que una de las razones más poderosas para usar import *en la __init__.pyimportación de paquetes es poder refactorizar un script que se ha convertido en múltiples scripts sin romper una aplicación existente. Pero si está diseñando un paquete desde el principio. Creo que es mejor dejar los __init__.pyarchivos vacíos.

por ejemplo:

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

entonces la aplicación crece y ahora es una carpeta completa

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

entonces el guión de inicio puede decir

__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 un script escrito para hacer lo siguiente no se rompa durante el cambio:

from foo import fooFactory, tallFoo, shortFoo
Cuervo de fuego
fuente
3
Estaba muy confundido sobre ' todo ' y la importación línea por línea. Tu ejemplo es muy esclarecedor.
Junchen
2
Estoy confundido por " __all__y import *es redundante", __all__es usado por el consumidor del módulo, y from foo import *es usado por el propio módulo para usar otros ...
Nick T
using __all__ and import * is redundant, only __all__ is needed ¿Cómo son esos redundantes? Ellos hacen cosas diferentes.
Endolith
113

Mis propios __init__.pyarchivos están vacíos la mayoría de las veces. En particular, nunca tengo un from blah import *como parte de __init__.py: si "importar el paquete" significa obtener todo tipo de clases, funciones, etc., definidas directamente como parte del paquete, entonces copiaría léxicamente el contenido del blah.pypaquete __init__.pyy lo eliminaría blah.py( la multiplicación de los archivos fuente no sirve de nada aquí).

Si insiste en apoyar las import *expresiones idiomáticas (eek), usar __all__(con una lista de nombres tan minúscula como pueda tener) puede ayudar a controlar el daño. En general, los espacios de nombres y las importaciones explícitas son cosas buenas , ¡y sugiero que reconsidere cualquier enfoque basado en omitir sistemáticamente uno o ambos conceptos! -)

Alex Martelli
fuente
9
Personalmente, prefiero mantener las cosas separadas y luego importar *. La razón es que, a pesar del plegado y demás, todavía odio buscar archivos que contienen demasiadas clases, incluso si están relacionados.
Stefano Borini
55
@stefano piensa en un gran marco. si se usa import *, debe aceptar incondicionalmente todo el marco en su totalidad, incluso las características que nunca usará. mantenerse __init__.pyvacío le brinda más oportunidades que solo semántica de todo o nada. pensar en retorcido.
mg.
si lo mantiene vacío, incluso después de importar mobilescouter, no se puede usar mobilescouter.mapper o mobilescouter.vehicle o mobilescouter.cualquier cosa. no es import mobilescouter.A, mobilescouter.B ..... demasiado detallado?
sunqiang
66
@sunqiang esto es personal pero no lo creo. from mobilescouter import A, Bes solo una línea de código y no tienes un proyecto con 666 clases y cada una con su propio archivo, ¿verdad? Si tiene dos o más import *en su código, está llenando el espacio de nombres con basura potencial y rápidamente olvidará de dónde Aviene. ¿Y si un paquete superior hace lo mismo? estás agarrando todos los subpaquetes y subpaquetes. Como dice el zen de Python, explícito es mejor que implícito.
mg.
1
@mg, si hay una línea "importar A, B" en el archivo init .py, entonces puedo llamar a A (o B) con la sintaxis: mobilescouter.A; si usamos "from mobilescouter import A, B", entonces es solo A. algo. a veces solo esta línea, no recuerdo que A sea un subpaquete de mobilescouter, y creo que esto contribuye a la contaminación del espacio de nombres (aunque es mucho mejor que "" from mobilescouter import * ". Todavía prefiero" import pkgname "dar usuario . la interfaz pública de manera uniforme init .PY hacer las cosas sub_pkgname importación.
sunqiang
1

Su __init__.pydebe tener una cadena de documentación .

Aunque toda la funcionalidad se implementa en módulos y subpaquetes, la cadena de documentación de su paquete es el lugar para documentar dónde comenzar. Por ejemplo, considere el paquete pythonemail . La documentación del paquete es una introducción que describe el propósito, los antecedentes y cómo los diversos componentes dentro del paquete funcionan juntos. Si genera automáticamente documentación de cadenas de documentos utilizando sphinx u otro paquete, la cadena de documentos del paquete es exactamente el lugar adecuado para describir dicha introducción.

Para cualquier otro contenido, vea las excelentes respuestas de firecrow y Alex Martelli .

gerrit
fuente
¿El actual __init__.pypara el emailpaquete sigue esta directriz? Veo una cadena de documentación de una sola línea que no hace mucho para explicar "cómo funcionan juntos los diversos componentes del paquete".
Gertlex
@Gertlex Quizás solo en la documentación web.
gerrit