6. Módulos
**********

Si sales del intérprete de Python y vuelves a entrar, las definiciones
que habías hecho (funciones y variables) se pierden. Por lo tanto, si
quieres escribir un programa más o menos largo, es mejor que utilices
un editor de texto para preparar la entrada para el intérprete y
ejecutarlo con ese archivo como entrada. Esto se conoce como crear un
*script*. A medida que tu programa crezca, quizás quieras separarlo en
varios archivos para que el mantenimiento sea más sencillo. Quizás
también quieras usar una función útil que has escrito en distintos
programas sin copiar su definición en cada programa.

Para soportar esto, Python tiene una manera de poner definiciones en
un archivo y usarlos en un script o en una instancia del intérprete.
Este tipo de ficheros se llama *módulo*; las definiciones de un módulo
pueden ser *importadas* a otros módulos o al módulo *principal* (la
colección de variables a las que tienes acceso en un script ejecutado
en el nivel superior y en el modo calculadora).

Un módulo es un fichero conteniendo definiciones y declaraciones de
Python. El nombre de archivo es el nombre del módulo con el sufijo
".py" agregado. Dentro de un módulo, el nombre del mismo módulo (como
cadena) está disponible en el valor de la variable global "__name__".
Por ejemplo, utiliza tu editor de texto favorito para crear un archivo
llamado "fibo.py" en el directorio actual, con el siguiente contenido:

   # Fibonacci numbers module

   def fib(n):    # write Fibonacci series up to n
       a, b = 0, 1
       while a < n:
           print(a, end=' ')
           a, b = b, a+b
       print()

   def fib2(n):   # return Fibonacci series up to n
       result = []
       a, b = 0, 1
       while a < n:
           result.append(a)
           a, b = b, a+b
       return result

Ahora entra en el intérprete de Python e importa este modulo con el
siguiente comando:

   >>> import fibo

Esto no añade los nombres de las funciones definidas en "fibo"
directamente en el espacio de nombres actual; sólo añade el nombre del
módulo "fibo". Usando el nombre del módulo puedes acceder a las
funciones:

   >>> fibo.fib(1000)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
   >>> fibo.fib2(100)
   [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
   >>> fibo.__name__
   'fibo'

Si pretendes utilizar una función frecuentemente puedes asignarla a un
nombre local:

   >>> fib = fibo.fib
   >>> fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377


6.1. Más sobre los módulos
==========================

Un módulo puede contener tanto declaraciones ejecutables como
definiciones de funciones. Estas declaraciones están pensadas para
inicializar el módulo. Se ejecutan únicamente la *primera* vez que el
módulo se encuentra en una declaración import. [1] (También se
ejecutan si el archivo se ejecuta como script.)

Cada módulo tiene su propio espacio de nombres, el cual es usado como
espacio de nombres global para todas las funciones definidas en el
módulo. Por lo tanto, el autor de un módulo puede usar variables
globales en el módulo sin preocuparse acerca de conflictos con una
variable global del usuario. Por otro lado, si sabes lo que estás
haciendo puedes acceder a las variables globales de un módulo con la
misma notación usada para referirte a sus funciones,
"nombremodulo.nombreitem".

Los módulos pueden importar otros módulos. Es costumbre pero no
obligatorio ubicar todas las declaraciones "import" al principio del
módulo (o script, para el caso). Los nombres de los módulos importados
son ubicados en el espacio de nombres global del módulo que hace la
importación.

Hay una variante de la declaración "import" que importa nos nombres de
un módulo directamente al espacio de nombres del módulo que hace la
importación. Por ejemplo:

   >>> from fibo import fib, fib2
   >>> fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Esto no introduce en el espacio de nombres local el nombre del módulo
desde el cual se está importando (por lo tanto, en el ejemplo, "fibo"
no esta definido).

Hay incluso una variante para importar todos los nombres que un módulo
define:

   >>> from fibo import *
   >>> fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Esto importa todos los nombres excepto los que inician con un guión
bajo ("_"). La mayoría de las veces los programadores de Python no
usan esto ya que introduce en el intérprete un conjunto de nombres
desconocido, posiblemente escondiendo algunas de las definiciones
previas.

Nota que en general la práctica de importar "*" de un módulo o paquete
está muy mal vista, ya que frecuentemente genera código poco legible.
Sin embargo, está bien usarlo para ahorrar tecleo en sesiones
interactivas.

Si el nombre del módulo es seguido por "as", el nombre siguiendo "as"
queda ligado directamente al módulo importado.

   >>> import fibo as fib
   >>> fib.fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Esto es básicamente importar el módulo de la misma forma que se haría
con "import fibo", con la única diferencia en que se encuentra
accesible como "fib".

También se puede utilizar cuando se utiliza "from" con efectos
similares:

   >>> from fibo import fib as fibonacci
   >>> fibonacci(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Nota:

  Por razones de eficiencia, cada módulo es importado solo una vez por
  sesión del intérprete. Por lo tanto, si cambias tus módulos, debes
  reiniciar el interprete -- ó, si es un solo módulo que quieres
  probar de forma interactiva, usa "importlib.reload()", por ejemplo:
  "import importlib; importlib.reload(modulename)".


6.1.1. Ejecutando módulos como scripts
--------------------------------------

Cuando ejecutes un módulo de Python con

   python fibo.py <arguments>

el código en el módulo será ejecutado, tal como si lo hubieses
importado, pero con "__name__" con el valor de ""__main__"".  Eso
significa que agregando este código al final de tu módulo:

   if __name__ == "__main__":
       import sys
       fib(int(sys.argv[1]))

puedes hacer que el archivo sea utilizable tanto como script, como
módulo importable, porque el código que analiza la línea de órdenes
sólo se ejecuta si el módulo es ejecutado como archivo principal:

   $ python fibo.py 50
   0 1 1 2 3 5 8 13 21 34

Si el módulo se importa, ese código no se ejecuta:

   >>> import fibo
   >>>

Esto es frecuentemente usado para proveer al módulo una interfaz de
usuario conveniente, o para propósitos de prueba (ejecutar el módulo
como un script ejecuta el juego de pruebas).


6.1.2. El camino de búsqueda de los módulos
-------------------------------------------

When a module named "spam" is imported, the interpreter first searches
for a built-in module with that name. These module names are listed in
"sys.builtin_module_names". If not found, it then searches for a file
named "spam.py" in a list of directories given by the variable
"sys.path".  "sys.path" is initialized from these locations:

* El directorio que contiene el script de entrada (o el directorio
  actual cuando no se especifica archivo).

* "PYTHONPATH" (una lista de nombres de directorios, con la misma
  sintaxis que la variable de la terminal "PATH").

* The installation-dependent default (by convention including a "site-
  packages" directory, handled by the "site" module).

Nota:

  En los sistemas de archivo que soportan enlaces simbólicos, el
  directorio que contiene el script de entrada es calculado luego de
  seguir el enlace simbólico. En otras palabras, el directorio que
  contiene el enlace simbólico **no** es agregado al camino de
  búsqueda del módulo.

Luego de la inicialización, los programas Python pueden modificar
"sys.path". El directorio que contiene el script que se está
ejecutando se ubica al principio de la búsqueda, adelante de la
biblioteca estándar. Esto significa que se cargarán scripts en ese
directorio en lugar de módulos de la biblioteca estándar con el mismo
nombre. Esto es un error a menos que se esté reemplazando
intencionalmente. Mirá la sección Módulos estándar para más
información.


6.1.3. Archivos "compilados" de Python
--------------------------------------

Para acelerar la carga de módulos, Python cachea las versiones
compiladas de cada módulo en el directorio "__pycache__" bajo el
nombre "module.*version*.pyc", dónde la versión codifica el formato
del archivo compilado; generalmente contiene el número de versión de
Python. Por ejemplo, en CPython *release* 3.3 la versión compilada de
spam.py sería cacheada como "__pycache__/spam.cpython-33.pyc". Este
convención de nombre permite compilar módulos desde diferentes
*releases* y versiones de Python para coexistir.

Python chequea la fecha de modificación de la fuente contra la versión
compilada para ver si esta es obsoleta y necesita ser recompilada.
Esto es un proceso completamente automático. También, los módulos
compilados son independientes de la plataforma, así que la misma
biblioteca puede ser compartida a través de sistemas con diferentes
arquitecturas.

Python no chequea el caché en dos circunstancias. Primero, siempre
recompila y no graba el resultado del módulo que es cargado
directamente desde la línea de comando. Segundo, no chequea el caché
si no hay módulo fuente. Para soportar una distribución sin fuente
(solo compilada), el módulo compilado debe estar en el directorio
origen, y no debe haber un módulo fuente.

Algunos consejos para expertos:

* Puedes usar los modificadores "-O" o "-OO" en el comando de Python
  para reducir el tamaño del módulo compilado. El modificador "-O"
  remueve las declaraciones *assert*, el modificador "-OO" remueve
  declaraciones *assert* y cadenas *__doc__*. Dado que algunos
  programas pueden confiar en tenerlos disponibles, solo deberías usar
  esta opción si conoces lo que estás haciendo. Los módulos
  "optimizados" tienen una etiqueta "opt-" y generalmente son mas
  pequeños. *Releases* futuras pueden cambiar los efectos de la
  optimización.

* Un programa no se ejecuta mas rápido cuando es leído de un archivo
  ".pyc" que cuando es leído de un archivo ".py"; la única cosa que es
  mas rápida en los archivos ".pyc" es la velocidad con la cual son
  cargados.

* El módulo "compileall" puede crear archivos .pyc para todos los
  módulos en un directorio.

* Hay mas detalle de este proceso, incluyendo un diagrama de flujo de
  decisiones, en **PEP 3147**.


6.2. Módulos estándar
=====================

Python viene con una biblioteca de módulos estándar, descrita en un
documento separado, la Referencia de la Biblioteca de Python (de aquí
en más, "Referencia de la Biblioteca").  Algunos módulos se integran
en el intérprete; estos proveen acceso a operaciones que no son parte
del núcleo del lenguaje pero que sin embargo están integrados, tanto
por eficiencia como para proveer acceso a primitivas del sistema
operativo, como llamadas al sistema.  El conjunto de tales módulos es
una opción de configuración el cual también depende de la plataforma
subyacente.  Por ejemplo, el módulo "winreg" sólo se provee en
sistemas Windows.  Un módulo en particular merece algo de atención:
"sys", el que está integrado en todos los intérpretes de Python.  Las
variables "sys.ps1" y "sys.ps2" definen las cadenas usadas como
cursores primarios y secundarios:

   >>> import sys
   >>> sys.ps1
   '>>> '
   >>> sys.ps2
   '... '
   >>> sys.ps1 = 'C> '
   C> print('Yuck!')
   Yuck!
   C>

Estas dos variables están solamente definidas si el intérprete está en
modo interactivo.

La variable "sys.path" es una lista de cadenas que determinan el
camino de búsqueda del intérprete para los módulos. Se inicializa por
omisión a un camino tomado de la variable de entorno "PYTHONPATH", o a
un valor predefinido en el intérprete si "PYTHONPATH" no está
configurada. Lo puedes modificar usando las operaciones estándar de
listas:

   >>> import sys
   >>> sys.path.append('/ufs/guido/lib/python')


6.3. La función "dir()"
=======================

La función integrada "dir()" se usa para encontrar qué nombres define
un módulo.  Retorna una lista ordenada de cadenas:

   >>> import fibo, sys
   >>> dir(fibo)
   ['__name__', 'fib', 'fib2']
   >>> dir(sys)  
   ['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
    '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
    '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
    '_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
    '_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
    'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
    'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
    'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
    'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
    'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
    'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
    'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
    'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
    'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
    'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
    'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
    'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
    'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
    'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
    'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
    'warnoptions']

Sin argumentos, "dir()" lista los nombres que tienes actualmente
definidos:

   >>> a = [1, 2, 3, 4, 5]
   >>> import fibo
   >>> fib = fibo.fib
   >>> dir()
   ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

Note que lista todos los tipos de nombres: variables, módulos,
funciones, etc.

"dir()" no lista los nombres de las funciones y variables integradas.
Si quieres una lista de esos, están definidos en el módulo estándar
"builtins":

   >>> import builtins
   >>> dir(builtins)  
   ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
    'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
    'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
    'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
    'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
    'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
    'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
    'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
    'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
    'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
    'NotImplementedError', 'OSError', 'OverflowError',
    'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
    'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
    'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
    'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
    'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
    'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
    'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
    '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
    'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
    'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
    'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
    'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
    'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
    'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
    'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
    'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
    'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
    'zip']


6.4. Paquetes
=============

Los Paquetes son una forma de estructurar el espacio de nombres de
módulos de Python usando "nombres de módulo con puntos". Por ejemplo,
el nombre del módulo "A.B" designa un submódulo "B" en un paquete
llamado "A". Así como el uso de módulos salva a los autores de
diferentes módulos de tener que preocuparse por los nombres de las
variables globales de cada uno, el uso de nombres de módulo con puntos
salva a los autores de paquetes con múltiples módulos, como NumPy o
Pillow de preocupaciones por los nombres de los módulos de cada uno.

Supongamos que quieres designar una colección de módulos (un
"paquete") para el manejo uniforme de archivos y datos de sonidos.
Hay diferentes formatos de archivos de sonido (normalmente reconocidos
por su extensión, por ejemplo: ".wav", ".aiff", ".au"), por lo que
tienes que crear y mantener una colección siempre creciente de módulos
para la conversión entre los distintos formatos de archivos. Hay
muchas operaciones diferentes que quizás quieras ejecutar en los datos
de sonido (como mezclarlos, añadir eco, aplicar una función
ecualizadora, crear un efecto estéreo artificial), por lo que además
estarás escribiendo una lista sin fin de módulos para realizar estas
operaciones.  Aquí hay una posible estructura para tu paquete
(expresados en términos de un sistema jerárquico de archivos):

   sound/                          Top-level package
         __init__.py               Initialize the sound package
         formats/                  Subpackage for file format conversions
                 __init__.py
                 wavread.py
                 wavwrite.py
                 aiffread.py
                 aiffwrite.py
                 auread.py
                 auwrite.py
                 ...
         effects/                  Subpackage for sound effects
                 __init__.py
                 echo.py
                 surround.py
                 reverse.py
                 ...
         filters/                  Subpackage for filters
                 __init__.py
                 equalizer.py
                 vocoder.py
                 karaoke.py
                 ...

Al importar el paquete, Python busca a través de los directorios en
"sys.path", buscando el sub-directorio del paquete.

Los archivos "__init__.py" son obligatorios para que Python trate los
directorios que contienen los archivos como paquetes.  Esto evita que
los directorios con un nombre común, como "string", oculten
involuntariamente módulos válidos que se producen luego en el camino
de búsqueda del módulo. En el caso mas simple, "__init__.py" puede ser
solo un archivo vacío, pero también puede ejecutar código de
inicialización para el paquete o el conjunto de variables "__all__",
descriptas luego.

Los usuarios del paquete pueden importar módulos individuales del
mismo, por ejemplo:

   import sound.effects.echo

Esto carga el submódulo "sound.effects.echo".  Debe hacerse referencia
al mismo con el nombre completo.

   sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

Otra alternativa para importar el submódulo es:

   from sound.effects import echo

Esto también carga el submódulo "echo", y lo deja disponible sin su
prefijo de paquete, por lo que puede usarse así:

   echo.echofilter(input, output, delay=0.7, atten=4)

Otra variación más es importar la función o variable deseadas
directamente:

   from sound.effects.echo import echofilter

De nuevo, esto carga el submódulo "echo", pero deja directamente
disponible a la función "echofilter()":

   echofilter(input, output, delay=0.7, atten=4)

Note que al usar "from package import item", el ítem puede ser tanto
un submódulo (o subpaquete) del paquete, o algún otro nombre definido
en el paquete, como una función, clase, o variable.  La declaración
"import" primero verifica si el ítem está definido en el paquete; si
no, asume que es un módulo y trata de cargarlo.  Si no lo puede
encontrar, se genera una excepción "ImportError".

Por otro lado, cuando se usa la sintaxis como "import
item.subitem.subsubitem", cada ítem excepto el último debe ser un
paquete; el mismo puede ser un módulo o un paquete pero no puede ser
una clase, función o variable definida en el ítem previo.


6.4.1. Importando * desde un paquete
------------------------------------

Ahora, ¿qué sucede cuando el usuario escribe "from sound.effects
import *"? Idealmente, uno esperaría que esto de alguna manera vaya al
sistema de archivos, encuentre cuales submódulos están presentes en el
paquete, y los importe a todos. Esto puede tardar mucho y el importar
sub-módulos puede tener efectos secundarios no deseados que sólo
deberían ocurrir cuando se importe explícitamente el sub-módulo.

La única solución es que el autor del paquete provea un índice
explícito del paquete.  La declaración "import" usa la siguiente
convención: si el código del "__init__.py" de un paquete define una
lista llamada "__all__", se toma como la lista de los nombres de
módulos que deberían ser importados cuando se hace "from package
import *".  Es tarea del autor del paquete mantener actualizada esta
lista cuando se libera una nueva versión del paquete.  Los autores de
paquetes podrían decidir no soportarlo, si no ven un uso para importar
* en sus paquetes.  Por ejemplo, el archivo
"sound/effects/__init__.py" podría contener el siguiente código:

   __all__ = ["echo", "surround", "reverse"]

This would mean that "from sound.effects import *" would import the
three named submodules of the "sound.effects" package.

Si no se define "__all__", la declaración "from sound.effects import
*" *no* importa todos los submódulos del paquete "sound.effects" al
espacio de nombres actual; sólo se asegura que se haya importado el
paquete "sound.effects" (posiblemente ejecutando algún código de
inicialización que haya en "__init__.py") y luego importa aquellos
nombres que estén definidos en el paquete.  Esto incluye cualquier
nombre definido (y submódulos explícitamente cargados) por
"__init__.py".  También incluye cualquier submódulo del paquete que
pudiera haber sido explícitamente cargado por declaraciones "import"
previas.  Considere este código:

   import sound.effects.echo
   import sound.effects.surround
   from sound.effects import *

En este ejemplo, los módulos "echo" y "surround" se importan en el
espacio de nombre actual porque están definidos en el paquete
"sound.effects" cuando se ejecuta la declaración "from...import".
(Esto también funciona cuando se define "__all__").

A pesar de que ciertos módulos están diseñados para exportar solo
nombres que siguen ciertos patrones cuando uses "import *", también se
considera una mala práctica en código de producción.

Recuerda, ¡no hay nada malo al usar "from package import
specific_submodule"! De hecho, esta es la notación recomendada a menos
que el módulo que importamos necesite usar submódulos con el mismo
nombre desde un paquete diferente.


6.4.2. Referencias internas en paquetes
---------------------------------------

Cuando se estructuran los paquetes en sub-paquetes (como en el ejemplo
"sound"), puedes usar "import" absolutos para referirte a submódulos
de paquetes hermanos.  Por ejemplo, si el módulo
"sound.filters.vocoder" necesita usar el módulo "echo" en el paquete
"sound.effects", puede hacer "from sound.effects import echo".

También puedes escribir "import" relativos con la forma "from module
import name".  Estos imports usan puntos adelante para indicar los
paquetes actuales o paquetes padres involucrados en el import
relativo. En el ejemplo "surround", podrías hacer:

   from . import echo
   from .. import formats
   from ..filters import equalizer

Note que los imports relativos se basan en el nombre del módulo
actual.  Ya que el nombre del módulo principal es siempre
""__main__"", los módulos pensados para usarse como módulo principal
de una aplicación Python siempre deberían usar "import" absolutos.


6.4.3. Paquetes en múltiples directorios
----------------------------------------

Los paquetes soportan un atributo especial más, "__path__".  Este se
inicializa a una lista que contiene el nombre del directorio donde
está el archivo "__init__.py" del paquete, antes de que el código en
ese archivo se ejecute.  Esta variable puede modificarse, afectando
búsquedas futuras de módulos y subpaquetes contenidos en el paquete.

Aunque esta característica no se necesita frecuentemente, puede usarse
para extender el conjunto de módulos que se encuentran en el paquete.

-[ Notas al pie ]-

[1] De hecho, las definiciones de funciones también son
    "declaraciones" que se "ejecutan"; la ejecución de una definición
    de función a nivel de módulo, ingresa el nombre de la función en
    el espacio de nombres global del módulo.
