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
This does not add the names of the functions defined in fibo
directly to
the current namespace (see Ámbitos y espacios de nombres en Python for more details);
it only adds the module name fibo
there. Using
the module name you can access the functions:
>>> 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.)
Each module has its own private namespace, which is used as the global namespace
by all functions defined in the module. Thus, the author of a module can
use global variables in the module without worrying about accidental clashes
with a user’s global variables. On the other hand, if you know what you are
doing you can touch a module’s global variables with the same notation used to
refer to its functions, modname.itemname
.
Modules can import other modules. It is customary but not required to place all
import
statements at the beginning of a module (or script, for that
matter). The imported module names, if placed at the top level of a module
(outside any functions or classes), are added to the module’s global namespace.
There is a variant of the import
statement that imports names from a
module directly into the importing module’s namespace. For example:
>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
This does not introduce the module name from which the imports are taken in the
local namespace (so in the example, fibo
is not defined).
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 terminalPATH
).El valor predeterminado dependiente de la instalación (por convención que incluye un directorio
site-packages
, manejado por el módulosite
).
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 etiquetaopt-
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.
The __init__.py
files are required to make Python treat directories
containing the file as packages. This prevents directories with a common name,
such as string
, from unintentionally hiding valid modules that occur later
on the module search path. In the simplest case, __init__.py
can just be
an empty file, but it can also execute initialization code for the package or
set the __all__
variable, described later.
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
In fact function definitions are also “statements” that are “executed”; the execution of a module-level function definition adds the function name to the module’s global namespace.