5. El sistema de importación
****************************

El código Python en un *módulo* obtiene acceso al código en otro
módulo por el proceso de *importarlo*.  La instrucción "import" es la
forma más común de invocar la maquinaria de importación, pero no es la
única manera.  Funciones como "importlib.import_module()" y built-in
"__import__()" también se pueden utilizar para invocar la maquinaria
de importación.

La instrucción "import" combina dos operaciones; busca el módulo con
nombre y, a continuación, enlaza los resultados de esa búsqueda a un
nombre en el ámbito local.  La operación de búsqueda de la instrucción
"import" se define como una llamada a la función "__import__()", con
los argumentos adecuados. El valor retornado de "__import__()" se
utiliza para realizar la operación de enlace de nombre de la
instrucción "import".  Consulte la instrucción "import" para obtener
los detalles exactos de esa operación de enlace de nombres.

Una llamada directa a "__import__()" realiza solo la búsqueda del
módulo y, si se encuentra, la operación de creación del módulo.
Aunque pueden producirse ciertos efectos secundarios, como la
importación de paquetes primarios y la actualización de varias
memorias caché (incluidas "sys.modules"), solo la instrucción "import"
realiza una operación de enlace de nombres.

Cuando se ejecuta una instrucción "import", se llama a la función
estándar incorporada "__import__()". Otros mecanismos para invocar el
sistema de importación (como "importlib.import_module()") pueden optar
por omitir "__import__()" y utilizar sus propias soluciones para
implementar la semántica de importación.

Cuando se importa un módulo por primera vez, Python busca el módulo y,
si se encuentra, crea un objeto de módulo [1], inicializándolo.  Si no
se encuentra el módulo con nombre, se genera un "ModuleNotFoundError".
Python implementa varias estrategias para buscar el módulo con nombre
cuando se invoca la maquinaria de importación.  Estas estrategias se
pueden modificar y ampliar mediante el uso de varios ganchos descritos
en las secciones siguientes.

Distinto en la versión 3.3: El sistema de importación se ha
actualizado para aplicar plenamente la segunda fase de **PEP 302**. Ya
no hay ninguna maquinaria de importación implícita: todo el sistema de
importación se expone a través de "sys.meta_path". Además, se ha
implementado la compatibilidad con paquetes de espacio de nombres
nativos (consulte **PEP 420**).


5.1. "importlib"
================

El módulo "importlib" proporciona una API enriquecida para interactuar
con el sistema de importación.  Por ejemplo
"importlib.import_module()" proporciona una API recomendada y más
sencilla que la integrada "__import__()" para invocar la maquinaria de
importación.  Consulte la documentación de la biblioteca "importlib"
para obtener más detalles.


5.2. Paquetes
=============

Python sólo tiene un tipo de objeto módulo, y todos los módulos son de
este tipo, independientemente de si el módulo está implementado en
Python, C, o en cualquier otro lenguaje.  Para ayudar a organizar los
módulos y proporcionar una jerarquía de nombres, Python tiene un
concepto de *paquete*.

Puedes pensar en los paquetes como los directorios de un sistema de
archivos y en los módulos como archivos dentro de los directorios,
pero no te tomes esta analogía demasiado literalmente, ya que los
paquetes y los módulos no tienen por qué originarse en el sistema de
archivos.  Para los propósitos de esta documentación, usaremos esta
conveniente analogía de directorios y archivos.  Al igual que los
directorios del sistema de archivos, los paquetes están organizados de
forma jerárquica, y los paquetes pueden contener subpaquetes, así como
módulos regulares.

Es importante tener en cuenta que todos los paquetes son módulos, pero
no todos los módulos son paquetes.  O dicho de otro modo, los paquetes
son sólo un tipo especial de módulo. Específicamente, cualquier módulo
que contenga un atributo "__path__" se considera un paquete.

All modules have a name.  Subpackage names are separated from their
parent package name by a dot, akin to Python's standard attribute
access syntax.  Thus you might have a package called "email", which in
turn has a subpackage called "email.mime" and a module within that
subpackage called "email.mime.text".


5.2.1. Paquetes regulares
-------------------------

Python define dos tipos de paquetes, *paquetes regulares* y *paquetes
de espacio de nombres*.  Los paquetes regulares son los paquetes
tradicionales tal y como existían en Python 3.2 y anteriores. Un
paquete regular se implementa típicamente como un directorio que
contiene un archivo "init__.py".  Cuando se importa un paquete
regular, este archivo "__init__.py" se ejecuta implícitamente, y los
objetos que define están vinculados a nombres en el espacio de nombres
del paquete.  El archivo "__init__.py" puede contener el mismo código
Python que puede contener cualquier otro módulo, y Python añadirá
algunos atributos adicionales al módulo cuando se importe.

Por ejemplo, la siguiente disposición del sistema de archivos define
un paquete "parent" de nivel superior con tres subpaquetes:

   parent/
       __init__.py
       one/
           __init__.py
       two/
           __init__.py
       three/
           __init__.py

Importando "parent.one" se ejecutará implícitamente
"parent/__init__.py" y "parent/one/__init__.py".  La importación
posterior de "parent.two" o "parent.three" ejecutará
"parent/two/__init__.py" y "parent/three/__init__.py" respectivamente.


5.2.2. Paquetes de espacio de nombres
-------------------------------------

Un paquete de espacio de nombres es un compuesto de varias
*porciones*, donde cada porción contribuye con un subpaquete al
paquete padre.  Las porciones pueden residir en diferentes lugares del
sistema de archivos.  Las porciones también pueden encontrarse en
archivos zip, en la red, o en cualquier otro lugar que Python busque
durante la importación.  Los paquetes de espacios de nombres pueden
corresponder o no directamente a objetos del sistema de archivos;
pueden ser módulos virtuales que no tienen una representación
concreta.

Los paquetes de espacios de nombres no usan una lista ordinaria para
su atributo "__path__". En su lugar utilizan un tipo iterable
personalizado que realizará automáticamente una nueva búsqueda de
porciones de paquete en el siguiente intento de importación dentro de
ese paquete si la ruta de su paquete padre (o "sys.path`" para un
paquete de nivel superior) cambia.

Con los paquetes de espacio de nombres, no hay ningún archivo
"parent/__init__.py".  De hecho, puede haber varios directorios
"padre" encontrados durante la búsqueda de importación, donde cada uno
de ellos es proporcionado por una parte diferente.  Por lo tanto,
"padre/one" no puede estar físicamente situado junto a "padre/two".
En este caso, Python creará un paquete de espacio de nombres para el
paquete "parent" de nivel superior siempre que se importe él o uno de
sus subpaquetes.

Consulte también **PEP 420** para conocer la especificación del
paquete de espacio de nombres.


5.3. Buscando
=============

Para comenzar la búsqueda, Python necesita el nombre *totalmente
calificado* del módulo (o paquete, pero para los fines de esta
discusión, la diferencia es irrelevante) que se está importando.  Este
nombre puede provenir de varios argumentos a la instrucción "import",
o de los parámetros de las funciones "importlib.import_module()" o
"__import__()".

Este nombre se utilizará en varias fases de la búsqueda de
importación, y puede ser la ruta de acceso punteada a un submódulo,
por ejemplo, "foo.bar.baz".  En este caso, Python primero intenta
importar "foo", luego "foo.bar", y finalmente "foo.bar.baz". Si se
produce un error en cualquiera de las importaciones intermedias, se
genera un "ModuleNotFoundError".


5.3.1. La caché del módulo
--------------------------

El primer lugar comprobado durante la búsqueda de importación es
"sys.modules".  Esta asignación sirve como caché de todos los módulos
que se han importado previamente, incluidas las rutas intermedias.
Por lo tanto, si "foo.bar.baz" se importó previamente, "sys.modules"
contendrá entradas para "foo", "foo.bar", y "foo.bar.baz".  Cada clave
tendrá como valor el objeto de módulo correspondiente.

Durante la importación, el nombre del módulo se busca en "sys.modules"
y si está presente, el valor asociado es el módulo que satisface la
importación y el proceso se completa.  Sin embargo, si el valor es
"None", se genera un "ModuleNotFoundError".  Si falta el nombre del
módulo, Python continuará buscando el módulo.

"sys.modules" se puede escribir.  La eliminación de una clave no puede
destruir el módulo asociado (ya que otros módulos pueden contener
referencias a él), pero invalidará la entrada de caché para el módulo
con nombre, lo que hará que Python busque de nuevo el módulo con
nombre en su próxima importación. La clave también se puede asignar a
"None", lo que obliga a la siguiente importación del módulo a dar como
resultado un "ModuleNotFoundError".

Tenga cuidado, sin embargo, como si mantiene una referencia al objeto
module, invalide su entrada de caché en "sys.modules" y, a
continuación, vuelva a importar el módulo con nombre, los dos objetos
de módulo *no* serán los mismos. Por el contrario,
"importlib.reload()" reutilizará el objeto de módulo *same* y
simplemente reinicializará el contenido del módulo volviendo a
ejecutar el código del módulo.


5.3.2. Buscadores y cargadores
------------------------------

Si el módulo con nombre no se encuentra en "sys.modules", se invoca el
protocolo de importación de Python para buscar y cargar el módulo.
Este protocolo consta de dos objetos conceptuales, *buscadores* y
*cargadores*. El trabajo de un buscador es determinar si puede
encontrar el módulo con nombre utilizando cualquier estrategia que
conozca. Los objetos que implementan ambas interfaces se conocen como
*importadores* se retornan a sí mismos cuando descubren que pueden
cargar el módulo solicitado.

Python incluye una serie de buscadores e importadores predeterminados.
El primero sabe cómo localizar módulos integrados, y el segundo sabe
cómo localizar módulos congelados.  Un tercer buscador predeterminado
busca módulos en *import path*.  El *import path* es una lista de
ubicaciones que pueden nombrar rutas del sistema de archivos o
archivos zip.  También se puede ampliar para buscar cualquier recurso
localizable, como los identificados por las direcciones URL.

La maquinaria de importación es extensible, por lo que se pueden
añadir nuevos buscadores para ampliar el alcance y el alcance de la
búsqueda de módulos.

En realidad, los buscadores no cargan módulos.  Si pueden encontrar el
módulo con nombre, retornan un *module spec*, una encapsulación de la
información relacionada con la importación del módulo, que la
maquinaria de importación utiliza al cargar el módulo.

En las secciones siguientes se describe el protocolo para buscadores y
cargadores con más detalle, incluido cómo puede crear y registrar
otros nuevos para ampliar la maquinaria de importación.

Distinto en la versión 3.4: En versiones anteriores de Python, los
buscadores retornaban *cargadores* directamente, mientras que ahora
retornen especificaciones de módulo que *contienen* cargadores. Los
cargadores todavía se utilizan durante la importación, pero tienen
menos responsabilidades.


5.3.3. Ganchos de importación
-----------------------------

La maquinaria de importación está diseñada para ser extensible; el
mecanismo principal para esto son los *ganchos de importación* (import
hooks).  Hay dos tipos de ganchos de importación: *meta hooks* (meta
ganchos) y *import path hooks* (ganchos de ruta de acceso de
importación).

Los meta ganchos se llaman al inicio del procesamiento de importación,
antes de que se haya producido cualquier otro procesamiento de
importación, que no sea búsqueda de caché de "sys.modules". Esto
permite que los metaganchos reemplacen el procesamiento de "sys.path",
módulos congelados o incluso módulos integrados.  Los meta ganchos se
registran agregando nuevos objetos de buscador a "sys.meta_path", como
se describe a continuación.

Los ganchos de ruta de acceso de importación se invocan como parte del
procesamiento "sys.path" (o "package.__path__"), en el punto donde se
encuentra su elemento de ruta de acceso asociado. Los ganchos de ruta
de acceso de importación se registran agregando nuevos invocables a
"sys.path_hooks" como se describe a continuación.


5.3.4. La meta ruta (*path*)
----------------------------

Cuando el módulo con nombre no se encuentra en "sys.modules", Python
busca a continuación "sys.meta_path", que contiene una lista de
objetos buscadores de metarutas.  Estos buscadores se consultan para
ver si saben cómo manejar el módulo nombrado.  Los buscadores de rutas
de meta deben implementar un método llamado "find_spec()" que toma
tres argumentos: un nombre, una ruta de importación y (opcionalmente)
un módulo de destino.  El buscador de metarutas puede usar cualquier
estrategia que desee para determinar si puede manejar el módulo con
nombre o no.

Si el buscador de metarutas sabe cómo controlar el módulo con nombre,
retorna un objeto de especificación.  Si no puede controlar el módulo
con nombre, retorna "None".  Si el procesamiento de "sys.meta_path"
llega al final de su lista sin retornar una especificación, se genera
un "ModuleNotFoundError".  Cualquier otra excepción provocada
simplemente se propaga hacia arriba, anulando el proceso de
importación.

El método de los buscadores de metarutas de "find_spec()" se llama con
dos o tres argumentos.  El primero es el nombre completo del módulo
que se está importando, por ejemplo "foo.bar.baz". El segundo
argumento son las entradas de ruta de acceso que se utilizarán para la
búsqueda de módulos.  Para los módulos de nivel superior, el segundo
argumento es "None", pero para submódulos o subpaquetes, el segundo
argumento es el valor del atributo "__path__" del paquete primario. Si
no se puede tener acceso al atributo "__path__" adecuado, se genera un
"ModuleNotFoundError".  El tercer argumento es un objeto de módulo
existente que será el destino de la carga más adelante. El sistema de
importación pasa un módulo de destino solo durante la recarga.

La metaruta se puede recorrer varias veces para una sola solicitud de
importación. Por ejemplo, suponiendo que ninguno de los módulos
implicados ya se haya almacenado en caché, la importación de
"foo.bar.baz" realizará primero una importación de nivel superior,
llamando a "mpf.find_spec("foo", None, None)" en cada buscador de
metarutas ("mpf"). Después de importar "foo" , "foo.bar" se importará
atravesando la meta ruta por segunda vez, llamando a
"mpf.find_spec("foo.bar", foo.__path__, None)". Una vez importado
"foo.bar", el recorrido final llamará a "mpf.find_spec("foo.bar.baz",
foo.bar.__path__, None)".

Algunos buscadores de metarutas solo admiten importaciones de nivel
superior. Estos importadores siempre retornarán "None" cuando se pase
algo distinto de "None" como segundo argumento.

El valor predeterminado de Python "sys.meta_path" tiene tres
buscadores de metarutas, uno que sabe cómo importar módulos
integrados, uno que sabe cómo importar módulos congelados y otro que
sabe cómo importar módulos desde un *import path* (es decir, el *path
based finder*).

Distinto en la versión 3.4: El método "find_spec()" de los buscadores
de metarutas de la ruta de acceso reemplazó "find_module()", que ahora
está en desuso. Aunque seguirá funcionando sin cambios, la maquinaria
de importación sólo lo intentará si el buscador no implementa
"find_spec()".

Distinto en la versión 3.10: El uso de "find_module()" por parte del
sistema de importación ahora lanza "ImportWarning".


5.4. Cargando
=============

Si se encuentra una especificación de módulo, la maquinaria de
importación la utilizará (y el cargador que contiene) al cargar el
módulo.  Aquí está una aproximación de lo que sucede durante la
porción de carga de la importación:

   module = None
   if spec.loader is not None and hasattr(spec.loader, 'create_module'):
       # It is assumed 'exec_module' will also be defined on the loader.
       module = spec.loader.create_module(spec)
   if module is None:
       module = ModuleType(spec.name)
   # The import-related module attributes get set here:
   _init_module_attrs(spec, module)

   if spec.loader is None:
       # unsupported
       raise ImportError
   if spec.origin is None and spec.submodule_search_locations is not None:
       # namespace package
       sys.modules[spec.name] = module
   elif not hasattr(spec.loader, 'exec_module'):
       module = spec.loader.load_module(spec.name)
       # Set __loader__ and __package__ if missing.
   else:
       sys.modules[spec.name] = module
       try:
           spec.loader.exec_module(module)
       except BaseException:
           try:
               del sys.modules[spec.name]
           except KeyError:
               pass
           raise
   return sys.modules[spec.name]

Tenga en cuenta los siguientes detalles:

   * Si hay un objeto de módulo existente con el nombre dado en
     "sys.modules", la importación ya lo habrá retornado.

   * El módulo existirá en "sys.modules" antes de que el cargador
     ejecute el código del módulo.  Esto es crucial porque el código
     del módulo puede (directa o indirectamente) importarse a sí
     mismo; agregándolo a "sys.modules" de antemano evita la
     recursividad sin límites en el peor de los casos y la carga
     múltiple en el mejor.

   * Si se produce un error en la carga, el módulo con errores -- y
     solo el módulo con errores -- se elimina de "sys.modules".
     Cualquier módulo que ya esté en la caché de "sys.modules" y
     cualquier módulo que se haya cargado correctamente como efecto
     secundario, debe permanecer en la memoria caché.  Esto contrasta
     con la recarga donde incluso el módulo que falla se deja en
     "sys.modules".

   * Después de crear el módulo pero antes de la ejecución, la
     maquinaria de importación establece los atributos del módulo
     relacionados con la importación ("_init_module_attrs" en el
     ejemplo de pseudocódigo anterior), como se resume en una sección
     posterior.

   * La ejecución del módulo es el momento clave de la carga en el que
     se rellena el espacio de nombres del módulo.  La ejecución se
     delega por completo en el cargador, lo que llega a decidir qué se
     rellena y cómo.

   * El módulo creado durante la carga y pasado a exec_module() puede
     no ser el que se retorna al final de la importación [2].

Distinto en la versión 3.4: El sistema de importación se ha hecho
cargo de las responsabilidades reutilizables de los cargadores.  Estos
fueron realizados previamente por el método
"importlib.abc.Loader.load_module()".


5.4.1. Cargadores
-----------------

Los cargadores de módulos proporcionan la función crítica de carga:
ejecución del módulo. La maquinaria de importación llama al método
"importlib.abc.Loader.exec_module()" con un único argumento, el objeto
module que se va a ejecutar.  Se omite cualquier valor retornado de
"exec_module()".

Los cargadores deben cumplir los siguientes requisitos:

   * Si el módulo es un módulo Python (a diferencia de un módulo
     integrado o una extensión cargada dinámicamente), el cargador
     debe ejecutar el código del módulo en el espacio de nombres
     global del módulo ("module.__dict__").

   * Si el cargador no puede ejecutar el módulo, debe generar un
     "ImportError", aunque se propagará cualquier otra excepción
     provocada durante "exec_module()".

En muchos casos, el buscador y el cargador pueden ser el mismo objeto;
en tales casos, el método "find_spec()" simplemente retornaría una
especificación con el cargador establecido en "self".

Los cargadores de módulos pueden optar por crear el objeto de módulo
durante la carga mediante la implementación de un método
"create_module()". Toma un argumento, la especificación del módulo, y
retorna el nuevo objeto de módulo que se usará durante la carga.
"create_module()" no necesita establecer ningún atributo en el objeto
module.  Si el método retorna "None", la maquinaria de importación
creará el nuevo módulo en sí.

Nuevo en la versión 3.4: El método de cargadores "create_module()".

Distinto en la versión 3.4: El método "load_module()" fue reemplazado
por "exec_module()" y la maquinaria de importación asumió todas las
responsabilidades reutilizables de la carga.Para la compatibilidad con
los cargadores existentes, la maquinaria de importación utilizará el
método de cargadores "load_module()" si existe y el cargador no
implementa también "exec_module()".  Sin embargo, "load_module()" ha
quedado obsoleto y los cargadores deben implementar "exec_module()" en
su lugar.El método "load_module()" debe implementar toda la
funcionalidad de carga reutilizable descrita anteriormente, además de
ejecutar el módulo.  Se aplican todas las mismas restricciones, con
algunas aclaraciones adicionales:

   * Si hay un objeto de módulo existente con el nombre dado en
     "sys.modules", el cargador debe utilizar ese módulo existente.
     (De lo contrario, "importlib.reload()" no funcionará
     correctamente.)  Si el módulo con nombre no existe en
     "sys.modules", el cargador debe crear un nuevo objeto de módulo y
     agregarlo a "sys.modules".

   * El módulo *debe* existir en "sys.modules" antes de que el
     cargador ejecute el código del módulo, para evitar la
     recursividad sin límites o la carga múltiple.

   * Si se produce un error en la carga, el cargador debe quitar los
     módulos que ha insertado en "sys.modules", pero debe quitar
     **solo** los módulos con errores, y solo si el propio cargador ha
     cargado los módulos explícitamente.

Distinto en la versión 3.5: A "DeprecationWarning" se genera cuando se
define "exec_module()" pero "create_module()" no lo es.

Distinto en la versión 3.6: Un "ImportError" se genera cuando
"exec_module()" está definido, pero "create_module()" no lo es.

Distinto en la versión 3.10: El uso de "load_module()" lanzará
"ImportWarning".


5.4.2. Submódulos
-----------------

Cuando se carga un submódulo mediante cualquier mecanismo (por
ejemplo, API "importlib", las instrucciones "import" o "import-from",
o "__import__()") integradas, se coloca un enlace en el espacio de
nombres del módulo primario al objeto submodule. Por ejemplo, si el
paquete "spam" tiene un submódulo "foo", después de importar
"spam.foo", "spam" tendrá un atributo "foo" que está enlazado al
submódulo.  Supongamos que tiene la siguiente estructura de
directorios:

   spam/
       __init__.py
       foo.py

and "spam/__init__.py" has the following line in it:

   from .foo import Foo

then executing the following puts name bindings for "foo" and "Foo" in
the "spam" module:

   >>> import spam
   >>> spam.foo
   <module 'spam.foo' from '/tmp/imports/spam/foo.py'>
   >>> spam.Foo
   <class 'spam.foo.Foo'>

Dadas las reglas de enlace de nombres familiares de Python, esto puede
parecer sorprendente, pero en realidad es una característica
fundamental del sistema de importación.  La retención invariable es
que si tiene "sys.modules[`spam`]" y "sys.modules[`spam.foo`]" (como
lo haría después de la importación anterior), este último debe
aparecer como el atributo "foo" de la primera.


5.4.3. Especificaciones del módulo
----------------------------------

La maquinaria de importación utiliza una variedad de información sobre
cada módulo durante la importación, especialmente antes de la carga.
La mayor parte de la información es común a todos los módulos.  El
propósito de las especificaciones de un módulo es encapsular esta
información relacionada con la importación por módulo.

El uso de una especificación durante la importación permite transferir
el estado entre los componentes del sistema de importación, por
ejemplo, entre el buscador que crea la especificación del módulo y el
cargador que la ejecuta.  Lo más importante es que permite a la
maquinaria de importación realizar las operaciones de caldera de
carga, mientras que sin una especificación de módulo el cargador tenía
esa responsabilidad.

La especificación del módulo se expone como el atributo "__spec__" en
un objeto de módulo. Consulte "ModuleSpec" para obtener más
información sobre el contenido de la especificación del módulo.

Nuevo en la versión 3.4.


5.4.4. Atributos de módulo relacionados con la importación
----------------------------------------------------------

La máquina de importación rellena estos atributos en cada objeto de
módulo durante la carga, en función de las especificaciones del
módulo, antes de que el cargador ejecute el módulo.

__name__

   The "__name__" attribute must be set to the fully qualified name of
   the module.  This name is used to uniquely identify the module in
   the import system.

__loader__

   El atributo "__loader__" debe establecerse en el objeto de cargador
   que utilizó la máquina de importación al cargar el módulo.  Esto es
   principalmente para la introspección, pero se puede utilizar para
   la funcionalidad específica del cargador adicional, por ejemplo,
   obtener datos asociados con un cargador.

__package__

   Se debe establecer el atributo "__package__" del módulo.  Su valor
   debe ser una cadena, pero puede ser el mismo valor que su
   "__name__".  Cuando el módulo es un paquete, su valor "__package__"
   debe establecerse en su "__name__".  Cuando el módulo no es un
   paquete, "__package__" debe establecerse en la cadena vacía para
   los módulos de nivel superior, o para los submódulos, en el nombre
   del paquete primario.  Consulte **PEP 366** para obtener más
   detalles.

   Este atributo se utiliza en lugar de "__name__" para calcular
   importaciones relativas explícitas para los módulos principales,
   tal como se define en **PEP 366**. Se espera que tenga el mismo
   valor que "__spec__.parent".

   Distinto en la versión 3.6: Se espera que el valor de "__package__"
   sea el mismo que "__spec__.parent".

__spec__

   El atributo "__spec__" debe establecerse en la especificación de
   módulo que se utilizó al importar el módulo. Establecer "__spec__"
   se aplica correctamente por igual a módulos inicializados durante
   el inicio del intérprete.  La única excepción es "__main__", donde
   "__spec__" es establecido None en algunos casos.

   Cuando "__package__" no está definido, "__spec__.parent" se utiliza
   como reserva.

   Nuevo en la versión 3.4.

   Distinto en la versión 3.6: "__spec__.parent" se utiliza como
   reserva cuando "__package__`" no está definido.

__path__

   Si el módulo es un paquete (normal o espacio de nombres), se debe
   establecer el atributo "__path__" del objeto de módulo.  El valor
   debe ser iterable, pero puede estar vacío si "__path__" no tiene
   más importancia. Si "__path__" no está vacío, debe producir cadenas
   cuando se itera. Más detalles sobre la semántica de "__path__" se
   dan below.

   Los módulos que no son de paquete no deben tener un atributo
   "__path__".

__file__

__cached__

   "__file__" es opcional. Si se establece, el valor de este atributo
   debe ser una cadena.  El sistema de importación puede optar por
   dejar "__file__" sin establecer si no tiene un significado
   semántico (por ejemplo, un módulo cargado desde una base de datos).

   Si se establece "__file__", también puede ser apropiado establecer
   el atributo "__cached__", que es la ruta de acceso a cualquier
   versión compilada del código (por ejemplo, archivo compilado por
   bytes). No es necesario que exista el archivo para establecer este
   atributo; la ruta de acceso puede simplemente apuntar a donde
   existiría el archivo compilado (consulte **PEP 3147**).

   También es apropiado establecer "__cached__" cuando "__file__" no
   está establecido.  Sin embargo, ese escenario es bastante atípico.
   En última instancia, el cargador es lo que hace uso de "__file__"
   y/o "__cached__".  Por lo tanto, si un cargador puede cargar desde
   un módulo almacenado en caché pero no se carga desde un archivo,
   ese escenario atípico puede ser adecuado.


5.4.5. module.__path__
----------------------

Por definición, si un módulo tiene un atributo "__path__", es un
paquete.

El atributo "__path__" de un paquete se utiliza durante las
importaciones de sus subpaquetes. Dentro de la maquinaria de
importación, funciona de la misma manera que "sys.path", es decir,
proporcionando una lista de ubicaciones para buscar módulos durante la
importación. Sin embargo, "__path__" suele estar mucho más restringido
que "sys.path".

"__path__" debe ser un iterable de cadenas, pero puede estar vacío.
Las mismas reglas utilizadas para "sys.path" también se aplican a la
"__path__" de un paquete, y "sys.path_hooks" (descrito a continuación)
se consultan al recorrer el "__path__" de un paquete.

El archivo "__init__.py" de un paquete puede establecer o modificar el
atributo "__path__" del paquete, y esta era normalmente la forma en
que los paquetes de espacio de nombres se implementaban antes de **PEP
420**.  Con la adopción de **PEP 420**, los paquetes de espacio de
nombres ya no necesitan proporcionar archivos "__init__.py" que
contienen solo el código de manipulación "__path__"; la máquina de
importación establece automáticamente "__path__" correctamente para el
paquete de espacio de nombres.


5.4.6. Representación (*Reprs*) de módulos
------------------------------------------

De forma predeterminada, todos los módulos tienen un repr utilizable,
sin embargo, dependiendo de los atributos establecidos anteriormente,
y en las especificaciones del módulo, puede controlar más
explícitamente el repr de los objetos de módulo.

Si el módulo tiene una especificación ("__spec__"), la maquinaria de
importación intentará generar un repr a partir de él.  Si eso falla o
no hay ninguna especificación, el sistema de importación creará un
repr predeterminado usando cualquier información disponible en el
módulo.  Intentará utilizar el "module.__name__", "module.__file__" y
"module.__loader__" como entrada en el repr, con valores
predeterminados para cualquier información que falte.

Aquí están las reglas exactas utilizadas:

   * Si el módulo tiene un atributo "__spec__", la información de la
     especificación se utiliza para generar el repr.  Se consultan los
     atributos "name", "loader", "origin" y "has_location".

   * Si el módulo tiene un atributo "__file__", se utiliza como parte
     del repr del módulo.

   * Si el módulo no tiene "__file__" pero tiene un "__loader__" que
     no es "None", entonces el repr del cargador se utiliza como parte
     del repr del módulo.

   * De lo contrario, sólo tiene que utilizar el "__name__" del módulo
     en el repr.

Distinto en la versión 3.4: El uso de "loader.module_repr()" ha
quedado obsoleto y la máquina de importación utiliza ahora la
especificación del módulo para generar un repr de módulo.Para la
compatibilidad con versiones anteriores de Python 3.3, el repr del
módulo se generará llamando al método "module_repr()" del cargador, si
se define, antes de probar cualquiera de los enfoques descritos
anteriormente.  Sin embargo, el método está en desuso.

Distinto en la versión 3.10: La llamada a "module_repr()" ahora ocurre
después de intentar usar el atributo "__spec__" de un módulo, pero
antes de recurrir a "__file__". Está previsto que el uso de
"module_repr()" se detenga en Python 3.12.


5.4.7. Invalidación del código de bytes en caché
------------------------------------------------

Antes de que Python cargue el código de bytes en caché de un archivo
".pyc", verifica si el caché está actualizado con el archivo ".py" de
origen. De forma predeterminada, Python hace esto almacenando la marca
de tiempo y el tamaño de la última modificación de la fuente en el
archivo de caché al escribirlo. En tiempo de ejecución, el sistema de
importación valida el archivo de caché comprobando los metadatos
almacenados en el archivo de caché con los metadatos de la fuente.

Python también admite archivos de caché "basados en hash", que
almacenan un hash del contenido del archivo de origen en lugar de sus
metadatos. Hay dos variantes de archivos ".pyc` basados en hash:
marcados y desmarcados. Para los archivos ``.pyc" marcados basados en
hash, Python valida el archivo de caché mediante el hash del archivo
de origen y la comparación del hash resultante con el hash en el
archivo de caché. Si se encuentra que un archivo de caché basado en
hash comprobado no es válido, Python lo regenera y escribe un nuevo
archivo de caché basado en hash comprobado. Para los archivos ".pyc"
sin marcar en hash, Python simplemente asume que el archivo de caché
es válido si existe. El comportamiento de validación de archivos
basado en hash ".pyc" se puede invalidar con el indicador "--check-
hash-based-pycs".

Distinto en la versión 3.7: Se han añadido archivos ".pyc" basados en
hash. Anteriormente, Python solo admitía la invalidación basada en la
marca de tiempo de la caché del código de bytes.


5.5. El buscador basado en rutas
================================

Como se mencionó anteriormente, Python viene con varios buscadores de
meta rutas predeterminados. Uno de ellos, llamado el buscador *path
based finder* ("PathFinder"), busca una *import path*, que contiene
una lista de *entradas de ruta*. Cada entrada de ruta de acceso nombra
una ubicación para buscar módulos.

El buscador basado en rutas en sí no sabe cómo importar nada. En su
lugar, atraviesa las entradas de ruta individuales, asociando cada una
de ellas con un buscador de entrada de ruta que sabe cómo manejar ese
tipo particular de ruta de acceso.

El conjunto predeterminado de buscadores de entradas de ruta
implementa toda la semántica para encontrar módulos en el sistema de
archivos, controlando tipos de archivos especiales como el código
fuente de Python (archivos "`.py"), el código de bytes de Python
(archivos ".pyc") y las bibliotecas compartidas (por ejemplo, archivos
".so`"). Cuando es compatible con el módulo "zipimport" en la
biblioteca estándar, los buscadores de entradas de ruta de acceso
predeterminados también controlan la carga de todos estos tipos de
archivo (excepto las bibliotecas compartidas) desde zipfiles.

Las entradas de ruta de acceso no deben limitarse a las ubicaciones
del sistema de archivos.  Pueden hacer referencia a direcciones URL,
consultas de base de datos o cualquier otra ubicación que se pueda
especificar como una cadena.

El buscador basado en rutas proporciona enlaces y protocolos
adicionales para que pueda ampliar y personalizar los tipos de
entradas de ruta de acceso que se pueden buscar.  Por ejemplo, si
desea admitir entradas de ruta de acceso como direcciones URL de red,
podría escribir un enlace que implemente la semántica HTTP para buscar
módulos en la web.  Este gancho (un al que se puede llamar) retornaría
un *path entry finder* compatible con el protocolo descrito a
continuación, que luego se utilizó para obtener un cargador para el
módulo de la web.

Una palabra de advertencia: esta sección y la anterior utilizan el
término *finder*, distinguiendo entre ellos utilizando los términos
*meta path finder* y *path entry finder*.  Estos dos tipos de
buscadores son muy similares, admiten protocolos similares y funcionan
de maneras similares durante el proceso de importación, pero es
importante tener en cuenta que son sutilmente diferentes. En
particular, los buscadores de meta path operan al principio del
proceso de importación, como se indica en el recorrido
"sys.meta_path".

Por el contrario, los buscadores de entradas de ruta son en cierto
sentido un detalle de implementación del buscador basado en rutas y,
de hecho, si el buscador basado en rutas se eliminara de
"sys.meta_path", no se invocaría ninguna semántica del buscador de
entradas de ruta.


5.5.1. Buscadores de entradas de ruta
-------------------------------------

El *path based finder* es responsable de encontrar y cargar módulos y
paquetes de Python cuya ubicación se especifica con una cadena *path
entry*.  La mayoría de las ubicaciones de nombres de entradas de ruta
de acceso en el sistema de archivos, pero no es necesario limitarlas a
esto.

Como buscador de meta rutas, el buscador *path based finder*
implementa el protocolo "find_spec()" descrito anteriormente, sin
embargo, expone enlaces adicionales que se pueden usar para
personalizar cómo se encuentran y cargan los módulos desde la ruta
*import path*.

Tres variables son usadas por *path based finder*, "sys.path",
"sys.path_hooks" y "sys.path_importer_cache".  También se utilizan los
atributos "__path__" en los objetos de paquete.  Estos proporcionan
formas adicionales de personalizar la maquinaria de importación.

"sys.path" contiene una lista de cadenas que proporcionan ubicaciones
de búsqueda para módulos y paquetes.  Se inicializa a partir de la
variable de entorno "PYTHONPATH" y varios otros valores
predeterminados específicos de la instalación e implementación.  Las
entradas de "sys.path" pueden nombrar directorios en el sistema de
archivos, archivos zip y potencialmente otras "ubicaciones" (consulte
el módulo "site") que se deben buscar para módulos, como direcciones
URL o consultas de base de datos.  Solo las cadenas y bytes deben
estar presentes en "sys.path"; todos los demás tipos de datos se
omiten.  La codificación de las entradas de bytes viene determinada
por los *buscadores de entrada de ruta*.

El buscador *path based finder* es un *meta path finder*, por lo que
la maquinaria de importación comienza la búsqueda *import path*
llamando al método "find_spec()" basado en la ruta de acceso, tal como
se describió anteriormente.  Cuando se proporciona el argumento "path"
a "find_spec()", será una lista de rutas de acceso de cadena para
recorrer - normalmente el atributo "__path__" de un paquete para una
importación dentro de ese paquete.  Si el argumento "path" es "None",
esto indica una importación de nivel superior y se utiliza "sys.path".

The path based finder iterates over every entry in the search path,
and for each of these, looks for an appropriate *path entry finder*
("PathEntryFinder") for the path entry.  Because this can be an
expensive operation (e.g. there may be "stat()" call overheads for
this search), the path based finder maintains a cache mapping path
entries to path entry finders.  This cache is maintained in
"sys.path_importer_cache" (despite the name, this cache actually
stores finder objects rather than being limited to *importer*
objects). In this way, the expensive search for a particular *path
entry* location's *path entry finder* need only be done once.  User
code is free to remove cache entries from "sys.path_importer_cache"
forcing the path based finder to perform the path entry search again
[3].

Si la entrada de ruta de acceso no está presente en la memoria caché,
el buscador basado en rutas de acceso recorre en iteración cada
llamada que se puede llamar en "sys.path_hooks".  Cada uno de los
enlaces de *ganchos de rutas de entrada* en esta lista se llama con un
solo argumento, la entrada de ruta de acceso que se va a buscar.  Esta
invocable puede retornar un *path entry finder* que puede controlar la
entrada de ruta de acceso, o puede generar "ImportError".  Un
"ImportError" es utilizado por el buscador basado en ruta para indicar
que el gancho no puede encontrar un *path entry finder* para eso
*entrada de ruta*.  Se omite la excepción y la iteración *import path*
continúa.  El enlace debe esperar un objeto de rutas o bytes; la
codificación de objetos bytes está hasta el enlace (por ejemplo, puede
ser una codificación del sistema de archivos, UTF-8, o algo más), y si
el gancho no puede decodificar el argumento, debe generar
"ImportError".

Si la iteración "sys.path_hooks" termina sin que se retorne ningún
valor *path entry finder*, a continuación, el método de búsqueda
basado en la ruta de acceso "find_spec()" almacenará "None" en
"sys.path_importer_cache" (para indicar que no hay ningún buscador
para esta entrada de ruta) y retornará "None", lo que indica que este
*meta path finder* no pudo encontrar el módulo.

Si un *path entry finder* *is* retornado por uno de los *path entry
hook* invocables en "sys.path_hooks", entonces el siguiente protocolo
se utiliza para pedir al buscador una especificación de módulo, que
luego se utiliza al cargar el módulo.

El directorio de trabajo actual, denotado por una cadena vacía, se
controla de forma ligeramente diferente de otras entradas de
"sys.path". En primer lugar, si se encuentra que el directorio de
trabajo actual no existe, no se almacena ningún valor en
"sys.path_importer_cache". En segundo lugar, el valor del directorio
de trabajo actual se busca actualizado para cada búsqueda de módulo.
En tercer lugar, la ruta de acceso utilizada para
"sys.path_importer_cache" y retornada por
"importlib.machinery.PathFinder.find_spec()" será el directorio de
trabajo actual real y no la cadena vacía.


5.5.2. Buscadores de entradas de ruta
-------------------------------------

Para admitir las importaciones de módulos y paquetes inicializados y
también para contribuir con partes a paquetes de espacio de nombres,
los buscadores de entradas de ruta de acceso deben implementar el
método "importlib.abc.PathEntryFinder.find_spec()".

"importlib.abc.PathEntryFinder.find_spec`()" toma dos argumentos: el
nombre completo del módulo que se va a importar y el módulo de destino
(opcional).  "find_spec()" retorna una especificación completamente
poblada para el módulo. Esta especificación siempre tendrá "cargador"
establecido (con una excepción).

Para indicar a la maquinaria de importación que la especificación
representa un espacio de nombres *portion*, el buscador de entrada de
ruta establece *"submodule_search_locations"* en una lista que
contiene la porción.

Distinto en la versión 3.4: "find_spec()" reemplazó a "find_loader()"
y "find_module()", los cuales ahora están en desuso, pero se
utilizarán si "find_spec()" no está definido.Los buscadores de
entradas de ruta más antiguos pueden implementar uno de estos dos
métodos en desuso en lugar de "find_spec()".  Los métodos todavía se
respetan en aras de la compatibilidad con versiones anteriores.  Sin
embargo, si "find_spec()" se implementa en el buscador de entrada de
ruta, se omiten los métodos heredados."find_loader()" toma un
argumento, el nombre completo del módulo que se está importando.
"find_loader()" devuelve una 2-tupla donde el primer elemento es el
cargador y el segundo elemento es un espacio de nombres *portion*.Para
la compatibilidad con versiones anteriores con otras implementaciones
del protocolo de importación, muchos buscadores de entradas de ruta de
acceso también admiten el mismo método tradicional "find_module()" que
admiten los buscadores de rutas de acceso meta. Sin embargo, nunca se
llama a los métodos del buscador de entradas de ruta "find_module()"
con un argumento "path" (se espera que registren la información de
ruta adecuada desde la llamada inicial al enlace de ruta).El método
"find_module()" en los buscadores de entrada de ruta está en desuso,
ya que no permite que el buscador de entradas de ruta de acceso aporte
partes a paquetes de espacio de nombres.  Si existen tanto
"find_loader()" como "find_module()" en un buscador de entrada de
ruta, el sistema de importación siempre llamará a "find_loader()" en
lugar de "find_module()".

Distinto en la versión 3.10: Las llamadas a "find_module()" y
"find_loader()" por parte del sistema de importación lanzarán
"ImportWarning".


5.6. Reemplazando el sistema de importación estándar
====================================================

El mecanismo más confiable para reemplazar todo el sistema de
importación es eliminar el contenido predeterminado de
"sys.meta_path", sustituyéndolos por completo por un enlace de meta
path personalizado.

Si es aceptable alterar únicamente el comportamiento de las
declaraciones de importación sin afectar a otras API que acceden al
sistema de importación, puede ser suficiente reemplazar la función
incorporada "__import__()". Esta técnica también puede emplearse a
nivel de módulo para alterar únicamente el comportamiento de las
declaraciones de importación dentro de ese módulo.

Para evitar selectivamente la importación de algunos módulos de un
enlace al principio de la meta path (en lugar de deshabilitar
completamente el sistema de importación estándar), es suficiente
elevar "ModuleNotFoundError" directamente desde "find_spec()" en lugar
de retornar "None". Este último indica que la búsqueda de meta path
debe continuar, mientras que la generación de una excepción termina
inmediatamente.


5.7. Paquete Importaciones relativas
====================================

Las importaciones relativas utilizan puntos iniciales. Un único punto
inicial indica una importación relativa, empezando por el paquete
actual. Dos o más puntos iniciales indican una importación relativa a
los elementos primarios del paquete actual, un nivel por punto después
del primero. Por ejemplo, dado el siguiente diseño de paquete:

   package/
       __init__.py
       subpackage1/
           __init__.py
           moduleX.py
           moduleY.py
       subpackage2/
           __init__.py
           moduleZ.py
       moduleA.py

En "subpackage1/moduleX.py" o "subpackage1/__init__.py", las
siguientes son importaciones relativas válidas:

   from .moduleY import spam
   from .moduleY import spam as ham
   from . import moduleY
   from ..subpackage1 import moduleY
   from ..subpackage2.moduleZ import eggs
   from ..moduleA import foo

Las importaciones absolutas pueden utilizar la sintaxis "import <>" o
"from <> import <>", pero las importaciones relativas solo pueden usar
el segundo formulario; la razón de esto es que:

   import XXX.YYY.ZZZ

debe exponer "XXX. Yyy. ZZZ" como una expresión utilizable, pero
.moduleY no es una expresión válida.


5.8. Consideraciones especiales para __main__
=============================================

El módulo "__main__" es un caso especial relativo al sistema de
importación de Python. Como se señaló elsewhere, el módulo "__main__"
se inicializa directamente al inicio del intérprete, al igual que
"sys" y "builtins". Sin embargo, a diferencia de esos dos, no califica
estrictamente como un módulo integrado. Esto se debe a que la forma en
que se inicializa "__main__" depende de las marcas y otras opciones
con las que se invoca el intérprete.


5.8.1. __main__.__spec__
------------------------

Dependiendo de cómo se inicializa "__main__", "__main__.__spec__" se
establece correctamente o en "None".

Cuando Python se inicia con la opción "-m", "__spec__" se establece en
la especificación de módulo del módulo o paquete correspondiente.
"__spec__" también se rellena cuando el módulo "__main__" se carga
como parte de la ejecución de un directorio, zipfile u otro "sys.path"
entrada.

En los casos restantes "__main__.__spec__" se establece en "None", ya
que el código utilizado para rellenar el "__main__" no se corresponde
directamente con un módulo importable:

* mensaje interactivo

* opción "-c"

* ejecutando desde stdin

* que se ejecuta directamente desde un archivo de código fuente o de
  código de bytes

Tenga en cuenta que "__main__.__spec__" siempre es "None" en el último
caso, *incluso si* el archivo técnicamente podría importarse
directamente como un módulo en su lugar. Utilice el modificador "-m"
si se desean metadatos de módulo válidos en "__main__".

Tenga en cuenta también que incluso cuando "__main__" corresponde a un
módulo importable y "__main__.__spec__" se establece en consecuencia,
todavía se consideran módulos *distinct*. Esto se debe al hecho de que
los bloques protegidos por las comprobaciones "if __name__ ==
"__main__":" solo se ejecutan cuando el módulo se utiliza para
rellenar el espacio de nombres "__main__", y no durante la importación
normal.


5.9. Referencias
================

La maquinaria de importación ha evolucionado considerablemente desde
los primeros días de Python.  La especificación original para paquetes
todavía está disponible para leer, aunque algunos detalles han
cambiado desde la escritura de ese documento.

La especificación original de "sys.meta_path" era **PEP 302**, con
posterior extensión en **PEP 420**.

**PEP 420** introdujo *paquetes de espacio de nombres* para Python
3.3.  **PEP 420** también introdujo el protocolo "find_loader()" como
alternativa a "find_module()".

**PEP 366** describe la adición del atributo "__package__" para las
importaciones relativas explícitas en los módulos principales.

**PEP 328** introdujo importaciones relativas absolutas y explícitas e
inicialmente propuestas "__name__" para la semántica **PEP 366**
eventualmente especificaría para "__package__".

**PEP 338** define la ejecución de módulos como scripts.

**PEP 451** agrega la encapsulación del estado de importación por
módulo en los objetos de especificación. También descargara la mayoría
de las responsabilidades de los cargadores en la maquinaria de
importación. Estos cambios permiten el desuso de varias API en el
sistema de importación y también la adición de nuevos métodos a los
buscadores y cargadores.

-[ Notas al Pie de Pagina ]-

[1] Véase "types. ModuleType".

[2] La implementación de importlib evita usar el valor retornado
    directamente. En su lugar, obtiene el objeto module buscando el
    nombre del módulo en "sys.modules".  El efecto indirecto de esto
    es que un módulo importado puede sustituirse a sí mismo en
    "sys.modules".  Este es un comportamiento específico de la
    implementación que no se garantiza que funcione en otras
    implementaciones de Python.

[3] En el código heredado, es posible encontrar instancias de "imp.
    NullImporter" en el "sys.path_importer_cache".  Se recomienda
    cambiar el código para usar "None" en su lugar.  Consulte Portando
    código Python para obtener más detalles.
