Respuestas:
Es una lista de objetos públicos de ese módulo, según la interpretación de import *
. Anula el valor predeterminado de ocultar todo lo que comienza con un guión bajo.
import *
(como, por ejemplo tk
). Una buena pista si este es el caso es la presencia de __all__
o nombres que comienzan con un guión bajo en el código del módulo.
tk
se publicaran hoy (o incluso en 2012), la práctica recomendada sería usar from tk import *
. Creo que la práctica se acepta por inercia, no por diseño intencional.
Vinculado, pero no mencionado explícitamente aquí, es exactamente cuando __all__
se usa. Es una lista de cadenas que definen qué símbolos en un módulo se exportarán cuando from <module> import *
se usen en el módulo.
Por ejemplo, el siguiente código de forma foo.py
explícita exporta los símbolos bar
y baz
:
__all__ = ['bar', 'baz']
waz = 5
bar = 10
def baz(): return 'baz'
Estos símbolos pueden importarse así:
from foo import *
print(bar)
print(baz)
# The following will trigger an exception, as "waz" is not exported by the module
print(waz)
Si __all__
se comenta lo anterior, este código se ejecutará hasta su finalización, ya que el comportamiento predeterminado de import *
es importar todos los símbolos que no comienzan con un guión bajo, desde el espacio de nombres dado.
Referencia: https://docs.python.org/tutorial/modules.html#importing-from-a-package
NOTA: solo __all__
afecta el from <module> import *
comportamiento. Los miembros que no se mencionan __all__
aún son accesibles desde fuera del módulo y se pueden importar con from <module> import <member>
.
print(baz())
?
print(baz)
imprime algo parecido a <function baz at 0x7f32bc363c10>
mientras que print(baz())
imprimebaz
¿Explicar __todos__ en Python?
Sigo viendo la variable
__all__
establecida en diferentes__init__.py
archivos.¿Qué hace esto?
__all__
hacer?Declara los nombres semánticamente "públicos" de un módulo. Si hay un nombre __all__
, se espera que los usuarios lo usen, y pueden esperar que no cambie.
También tendrá efectos programáticos:
import *
__all__
en un módulo, por ejemplo module.py
:
__all__ = ['foo', 'Bar']
significa que, import *
desde el módulo, solo se importan los nombres en el __all__
:
from module import * # imports foo and Bar
Las herramientas de autocompletado de código y documentación pueden (de hecho, deberían) también inspeccionar __all__
para determinar qué nombres mostrar como disponibles desde un módulo.
__init__.py
convierte un directorio en un paquete de PythonDe los documentos :
Los
__init__.py
archivos son necesarios para que Python trate los directorios como paquetes; Esto se hace para evitar que los directorios con un nombre común, como cadena, oculten involuntariamente módulos válidos que se producen más adelante en la ruta de búsqueda del módulo.En el caso más simple,
__init__.py
puede ser un archivo vacío, pero también puede ejecutar el código de inicialización del paquete o establecer el__all__
variable.
Entonces __init__.py
puede declarar el __all__
para un paquete .
Un paquete generalmente está compuesto por módulos que pueden importarse entre sí, pero que necesariamente están vinculados con un __init__.py
archivo. Ese archivo es lo que hace que el directorio sea un paquete de Python real. Por ejemplo, supongamos que tiene los siguientes archivos en un paquete:
package
├── __init__.py
├── module_1.py
└── module_2.py
Creemos estos archivos con Python para que pueda seguirlos: puede pegar lo siguiente en un shell de 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
""")
Y ahora ha presentado una API completa que otra persona puede usar cuando importan su paquete, así:
import package
package.foo()
package.Bar()
Y el paquete no tendrá todos los demás detalles de implementación que usó al crear sus módulos abarrotando el package
espacio de nombres.
__all__
en __init__.py
Después de más trabajo, tal vez haya decidido que los módulos son demasiado grandes (¿como muchos miles de líneas?) Y deben dividirse. Entonces haces lo siguiente:
package
├── __init__.py
├── module_1
│ ├── foo_implementation.py
│ └── __init__.py
└── module_2
├── Bar_implementation.py
└── __init__.py
Primero haga los directorios de subpaquete con los mismos nombres que los módulos:
subpackage_1 = package / 'module_1'
subpackage_1.mkdir()
subpackage_2 = package / 'module_2'
subpackage_2.mkdir()
Mover las implementaciones:
package_module_1.rename(subpackage_1 / 'foo_implementation.py')
package_module_2.rename(subpackage_2 / 'Bar_implementation.py')
cree __init__.py
s para los subpaquetes que declaran el __all__
para cada:
(subpackage_1 / '__init__.py').write_text("""
from .foo_implementation import *
__all__ = ['foo']
""")
(subpackage_2 / '__init__.py').write_text("""
from .Bar_implementation import *
__all__ = ['Bar']
""")
Y ahora todavía tiene la API aprovisionada a nivel de paquete:
>>> import package
>>> package.foo()
>>> package.Bar()
<package.module_2.Bar_implementation.Bar object at 0x7f0c2349d210>
Y puede agregar fácilmente cosas a su API que puede administrar en el nivel de subpaquete en lugar del nivel de módulo del subpaquete. Si desea agregar un nuevo nombre a la API, simplemente actualice __init__.py
, por ejemplo, en module_2:
from .Bar_implementation import *
from .Baz_implementation import *
__all__ = ['Bar', 'Baz']
Y si no está listo para publicar Baz
en la API de nivel superior, en su nivel superior __init__.py
podría tener:
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
y si sus usuarios conocen la disponibilidad de Baz
, pueden usarla:
import package
package.Baz()
pero si no lo saben, otras herramientas (como pydoc ) no les informarán.
Más tarde puede cambiar eso cuando Baz
esté listo para el horario estelar:
from .module_1 import *
from .module_2 import *
__all__ = ['foo', 'Bar', 'Baz']
_
versus__all__
:Por defecto, Python exportará todos los nombres que no comiencen con un _
. Ciertamente podría confiar en este mecanismo. Algunos paquetes de la biblioteca estándar de Python, de hecho, no se basan en esto, pero para hacerlo, ellos alias de sus importaciones, por ejemplo, en ctypes/__init__.py
:
import os as _os, sys as _sys
Usar la _
convención puede ser más elegante porque elimina la redundancia de nombrar los nombres nuevamente. Pero agrega la redundancia para las importaciones (si tiene muchas) y es fácil olvidarse de hacer esto constantemente, y lo último que desea es tener que respaldar indefinidamente algo que pretendía ser solo un detalle de implementación, solo porque olvidó prefijar un _
al nombrar una función.
Personalmente, escribo una de las __all__
primeras etapas de mi ciclo de vida de desarrollo para módulos para que otras personas que puedan usar mi código sepan qué deben usar y qué no.
La mayoría de los paquetes en la biblioteca estándar también usan __all__
.
__all__
tiene sentidoTiene sentido apegarse a la _
convención de prefijo en lugar de __all__
cuando:
export
decoradorLa desventaja de usar __all__
es que tiene que escribir los nombres de las funciones y clases que se exportan dos veces, y la información se mantiene separada de las definiciones. nos podía usar un decorador para resolver este problema.
La idea de un decorador de exportación de este tipo surgió de la charla de David Beazley sobre el embalaje. Esta implementación parece funcionar bien en el importador tradicional de CPython. Si tiene un gancho o sistema de importación especial, no lo garantizo, pero si lo adopta, es bastante trivial retirarse: solo tendrá que agregar manualmente los nombres nuevamente en el__all__
Entonces, por ejemplo, en una biblioteca de utilidades, definiría el 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
y luego, donde definirías un __all__
, haces esto:
$ 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()
Y esto funciona bien si se ejecuta como principal o importado por otra función.
$ cat > run.py
import main
main.main()
$ python run.py
main
Y el aprovisionamiento de API import *
también 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
y el uso de__all__
__all__
es correcto.
__all__
también, pero diría que tienes una API inestable ... Esto sería algo para tener algunas pruebas de aceptación exhaustivas.
module_1
y module_2
; ¿Está bien incluir un explícito del module_1
en __init__.py
? ¿Me equivoco al pensar que esto vale la pena?
Solo estoy agregando esto para ser precisos:
Todas las demás respuestas se refieren a módulos . La pregunta original mencionada explícitamente __all__
en los __init__.py
archivos, por lo que se trata de paquetes de Python .
En general, __all__
solo entra en juego cuando se utiliza la from xxx import *
variante de la import
declaración. Esto se aplica tanto a los paquetes como a los módulos.
El comportamiento de los módulos se explica en las otras respuestas. El comportamiento exacto de los paquetes se describe aquí en detalle.
En resumen, __all__
a nivel de paquete hace aproximadamente lo mismo que para los módulos, excepto que trata con módulos dentro del paquete (en contraste con la especificación de nombres dentro del módulo ). Por lo tanto, __all__
especifica todos los módulos que se cargarán e importarán en el espacio de nombres actual cuando lo usemos from package import *
.
La gran diferencia es que cuando omite la declaración de __all__
un paquete __init__.py
, la declaración from package import *
no importará nada (con las excepciones explicadas en la documentación, consulte el enlace anterior).
Por otro lado, si omite __all__
en un módulo, la "importación destacada" importará todos los nombres (que no comiencen con un guión bajo) definidos en el módulo.
from package import *
aún importará todo lo definido en __init__.py
, incluso si no hay all
. La diferencia importante es que sin __all__
él no importará automáticamente ningún módulo definido en el directorio del paquete.
También cambia lo que mostrará pydoc:
module1.py
a = "A"
b = "B"
c = "C"
module2.py
__all__ = ['a', 'b']
a = "A"
b = "B"
c = "C"
$ pydoc module1
Ayuda sobre el módulo module1: NOMBRE módulo 1 ARCHIVO module1.py DATOS a = 'A' b = 'B' c = 'C'
$ pydoc module2
Ayuda sobre el módulo module2: NOMBRE módulo2 ARCHIVO module2.py DATOS __todos__ = ['a', 'b'] a = 'A' b = 'B'
Declaro __all__
en todos mis módulos, así como subrayar los detalles internos, estos realmente ayudan cuando se usan cosas que nunca antes has usado en sesiones de intérpretes en vivo.
__all__
personaliza *
enfrom <module> import *
__all__
personaliza *
enfrom <package> import *
Un módulo es un .py
archivo destinado a ser importado.
Un paquete es un directorio con un __init__.py
archivo. Un paquete generalmente contiene módulos.
""" cheese.py - an example module """
__all__ = ['swiss', 'cheddar']
swiss = 4.99
cheddar = 3.99
gouda = 10.99
__all__
les permite a los humanos conocer las características "públicas" de un módulo . [ @AaronHall ] Además, pydoc los reconoce. [ @Longpoke ]
Vea cómo swiss
y cheddar
se introducen en el espacio de nombres local, pero no 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
Sin __all__
, cualquier símbolo (que no comience con un guión bajo) habría estado disponible.
*
no se ven afectadas 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)
En el __init__.py
archivo de un paquete __all__
hay una lista de cadenas con los nombres de módulos públicos u otros objetos. Esas características están disponibles para las importaciones de comodines. Al igual que con los módulos, __all__
personaliza la *
importación de comodines desde el paquete. [ @MartinStettner ]
Aquí hay un extracto del conector Python MySQL __init__.py
:
__all__ = [
'MySQLConnection', 'Connect', 'custom_error_exception',
# Some useful constants
'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
'HAVE_CEXT',
# Error handling
'Error', 'Warning',
...etc...
]
El caso predeterminado, un asterisco sin __all__
un paquete , es complicado, porque el comportamiento obvio sería costoso: usar el sistema de archivos para buscar todos los módulos en el paquete. En cambio, en mi lectura de los documentos, solo se importan los objetos definidos en __init__.py
:
Si
__all__
no está definido, la declaraciónfrom sound.effects import *
no no importar todos los submódulos del paquetesound.effects
en el espacio de nombres actual; solo se asegura de que el paquetesound.effects
se haya importado (posiblemente ejecutando cualquier código de inicialización__init__.py
) y luego importa los nombres definidos en el paquete. Esto incluye cualquier nombre definido (y submódulos cargados explícitamente) por__init__.py
. También incluye todos los submódulos del paquete que se cargaron explícitamente en declaraciones de importación anteriores.
Las importaciones de comodines ... deben evitarse ya que [confunden] a los lectores y muchas herramientas automatizadas.
[ PEP 8 , @ToolmakerSteve]
from <package> import *
sin __all__
en __init__.py
que está no importando cualquiera de los módulos .
__init__.py
fuera un módulo . Pero no estoy seguro de que sea exacto, o en particular si se excluyen los objetos con subrayado subrayado. Además, separé más claramente las secciones sobre MÓDULOS y PAQUETES. ¿Tus pensamientos?
De (Un No Oficial) Python Reference Wiki :
Los nombres públicos definidos por un módulo se determinan verificando el espacio de nombres del módulo para una variable nombrada
__all__
; si está definido, debe ser una secuencia de cadenas que son nombres definidos o importados por ese módulo.__all__
Todos los nombres dados se consideran públicos y deben existir. Si__all__
no está definido, el conjunto de nombres públicos incluye todos los nombres encontrados en el espacio de nombres del módulo que no comienzan con un carácter de subrayado ("_").__all__
debe contener la API pública completa. Su objetivo es evitar la exportación accidental de elementos que no forman parte de la API (como los módulos de biblioteca que se importaron y utilizaron dentro del módulo).
__all__
se usa para documentar la API pública de un módulo de Python. Aunque es opcional, __all__
debe usarse.
Aquí está el extracto relevante de la referencia del lenguaje Python :
Los nombres públicos definidos por un módulo se determinan verificando el espacio de nombres del módulo para una variable nombrada
__all__
; si se define, debe ser una secuencia de cadenas que son nombres definidos o importados por ese módulo.__all__
Todos los nombres dados se consideran públicos y deben existir. Si__all__
no está definido, el conjunto de nombres públicos incluye todos los nombres encontrados en el espacio de nombres del módulo que no comienzan con un carácter de subrayado ('_').__all__
debe contener la API pública completa. Su objetivo es evitar la exportación accidental de elementos que no forman parte de la API (como los módulos de biblioteca que se importaron y utilizaron dentro del módulo).
PEP 8 usa una redacción similar, aunque también deja en claro que los nombres importados no son parte de la API pública cuando __all__
está ausente:
Para admitir mejor la introspección, los módulos deben declarar explícitamente los nombres en su API pública utilizando el
__all__
atributo Establecer__all__
una lista vacía indica que el módulo no tiene una API pública.[...]
Los nombres importados siempre deben considerarse un detalle de implementación. Otros módulos no deben confiar en el acceso indirecto a dichos nombres importados a menos que sean una parte documentada explícitamente de la API del módulo que los contiene, como
os.path
un__init__
módulo de paquete que expone la funcionalidad de los submódulos.
Además, como se señaló en otras respuestas, __all__
se utiliza para habilitar la importación de comodines para paquetes :
La declaración de importación utiliza la siguiente convención: si el
__init__.py
código de un paquete define una lista nombrada__all__
, se considera que es la lista de nombres de módulos que deben importarse cuandofrom package import *
se encuentra.
__all__
afecta las from <module> import *
declaraciones.
Considere este ejemplo:
foo
├── bar.py
└── __init__.py
En foo/__init__.py
:
(Implícito) Si no definimos __all__
, from foo import *
solo importaremos los nombres definidos en foo/__init__.py
.
(Explícito) Si definimos __all__ = []
, entonces from foo import *
no importará nada.
(Explícito) Si definimos __all__ = [ <name1>, ... ]
, from foo import *
solo importaremos esos nombres.
Tenga en cuenta que, en el caso implícito, python no importará nombres que comiencen por _
. Sin embargo, puede forzar la importación de dichos nombres utilizando__all__
.
Puede ver el documento de Python aquí .
__all__
afecta cómo from foo import *
funciona
El código que está dentro del cuerpo de un módulo (pero no en el cuerpo de una función o clase) puede usar un asterisco ( *
) en una from
declaración:
from foo import *
Las *
solicitudes de que todos los atributos del módulo foo
(excepto los que comienzan con guiones bajos) se unan como variables globales en el módulo de importación. Cuando foo
tiene un atributo __all__
, el valor del atributo es la lista de los nombres que están vinculados por este tipo defrom
declaración.
Si foo
es un paquete y __init__.py
define una lista llamada __all__
, se considera que es la lista de nombres de submódulos que deben importarse cuando from foo import *
se encuentran. Si __all__
no está definido, la instrucción from foo import *
importa los nombres definidos en el paquete. Esto incluye cualquier nombre definido (y submódulos cargados explícitamente) por __init__.py
.
Tenga en cuenta que __all__
no tiene que ser una lista. Según la documentación de la import
declaración , si está definida, __all__
debe ser una secuencia de cadenas que son nombres definidos o importados por el módulo. Por lo tanto, también puede usar una tupla para ahorrar memoria y ciclos de CPU. Simplemente no olvide una coma en caso de que el módulo defina un solo nombre público:
__all__ = ('some_name',)
Consulte también ¿Por qué es malo "importar *"?
Esto se define en PEP8 aquí :
Nombres de variables globales
(Esperemos que estas variables estén diseñadas para usarse solo dentro de un módulo). Las convenciones son casi las mismas que para las funciones.
Los módulos diseñados para su uso a través de
from M import *
deben usar el__all__
mecanismo para evitar la exportación de globales, o utilizar la convención más antigua de prefijar tales globales con un guión bajo (lo que es posible que desee hacer para indicar que estos globales son "módulo no público").
PEP8 proporciona convenciones de codificación para el código de Python que comprende la biblioteca estándar en la distribución principal de Python. Cuanto más sigas esto, más cerca estarás de la intención original.
__all__
si__all__
está presente, no están exactamente ocultos; pueden verse y accederse perfectamente normalmente si conoce sus nombres. Solo en el caso de una "importación *", que de todos modos no se recomienda, la distinción tiene algún peso.