Python: Módulos y paquetes

Módulos

Para facilitar el mantenimiento y la lectura los programas demasiado largos pueden dividirse en módulos, agrupando elementos relacionados. Los módulos son entidades que permiten una organización y división lógica de nuestro código. Los ficheros son su contrapartida física: cada archivo Python almacenado en disco equivale a un módulo.

Vamos a crear nuestro primer módulo entonces creando un pequeño archivo modulo.py con el siguiente contenido:

def mi_funcion():
    print "una funcion"

class MiClase:
    def __init__(self):
        print "una clase"

print "un modulo"


Si quisiéramos utilizar la funcionalidad definida en este módulo en nuestro programa tendríamos que importarlo. Para importar un módulo se utiliza la palabra clave import seguida del nombre del módulo, que consiste en el nombre del archivo menos la extensión. Como ejemplo, creemos un archivo programa.py en el mismo directorio en el que guardamos el archivo del módulo, con el siguiente contenido:

import modulo

modulo.mi_funcion()

El import no solo hace que tengamos disponible todo lo definido dentro del módulo, sino que también ejecuta el código del módulo. Por esta razón nuestro programa, además de imprimir el texto “una funcion” al llamar a mi_funcion, también imprimiría el texto “un modulo”, debido al print del módulo importado. No se imprimiría, no obstante, el texto “una clase”, ya que lo que se hizo en el módulo fue tan solo definir de la clase, no instanciarla.

La clausula import también permite importar varios módulos en la misma línea. En el siguiente ejemplo podemos ver cómo se importa con una sola clausula import los módulos de la distribución por defecto de Python os, que engloba funcionalidad relativa al sistema operativo; sys, con funcionalidad relacionada con el propio intérprete de Python y time, en el que se almacenan funciones para manipular fechas y horas.

import os, sys, time

print time.asctime()

Sin duda os habréis fijado en este y el anterior ejemplo en un detalle importante, y es que, como vemos, es necesario preceder el nombre de los objetos que importamos de un módulo con el nombre del módulo al que pertenecen, o lo que es lo mismo, el espacio de nombres en el que se encuentran. Esto permite que no sobreescribamos accidentalmente algún otro objeto que tuviera el mismo nombre al importar otro módulo.

Sin embargo es posible utilizar la construcción fromimport para ahorrarnos el tener que indicar el nombre del módulo antes del objeto que nos interesa. De esta forma se importa el objeto o los objetos que indiquemos al espacio de nombres actual.

from time import asctime

print asctime()

Aunque se considera una mala práctica, también es posible importar todos los nombres del módulo al espacio de nombres actual usando el caracter ‘*’:

from time import *

Ahora bien, recordareis que a la hora de crear nuestro primer módulo insistí en que lo guardarais en el mismo directorio en el que se encontraba el programa que lo importaba. Entonces, ¿cómo podemos importar los módulos os, sys o time si no se encuentran los archivos os.py, sys.py y time.py en el mismo directorio?

A la hora de importar un módulo Python recorre todos los directorios indicados en la variable de entorno PYTHONPATH en busca de un archivo con el nombre adecuado. El valor de la variable PYTHONPATH se puede consultar desde Python mediante sys.path

>>> import sys
>>> sys.path

De esta forma para que nuestro módulo estuviera disponible para todos los programas del sistema bastaría con que lo copiáramos a uno de los directorios indicados en PYTHONPATH.

En el caso de que Python no encontrara ningún módulo con el nombre especificado, se lanzaría una excepción de tipo ImportError.

Por último es interesante comentar que en Python los módulos también son objetos; de tipo module en concreto. Por supuesto esto significa que pueden tener atributos y métodos. Uno de sus atributos, __name__, se utiliza a menudo para incluir código ejecutable en un módulo pero que este sólo se ejecute si se llama al módulo como programa, y no al importarlo. Para lograr esto basta saber que cuando se ejecuta el módulo directamente __name__ tiene como valor __main__, mientras que cuando se importa, el valor de __name__ es el nombre del módulo:

print "Se muestra siempre"

if __name__ == "__main__":
    print "Se muestra si no es importacion"

Otro atributo interesante es __doc__, que, como en el caso de funciones y clases, sirve a modo de documentación del objeto (docstring o cadena de documentación). Su valor es el de la primera línea del cuerpo del módulo, en el caso de que esta sea una cadena de texto; en caso contrario valdrá None.

Paquetes

Si los módulos sirven para organizar el código, los paquetes sirven para organizar los módulos. Los paquetes son tipos especiales de módulos (ambos son de tipo module) que permiten agrupar módulos relacionados. Mientras los módulos se corresponden a nivel físico con los archivos, los paquetes se representan mediante directorios.

En una aplicación cualquiera podríamos tener, por ejemplo, un paquete iu para la interfaz o un paquete bbdd para la persistencia a base de datos.

Para hacer que Python trate a un directorio como un paquete es necesario crear un archivo __init__.py en dicha carpeta. En este archivo se pueden definir elementos que pertenezcan a dicho paquete, como una constante DRIVER para el paquete bbdd, aunque habitualmente se tratará de un archivo vacío. Para hacer que un cierto módulo se encuentre dentro de un paquete, basta con copiar el archivo que define el módulo al directorio del paquete.

Como los modulos, para importar paquetes también se utiliza import y fromimport y el caracter ‘.’ para separar paquetes, subpaquetes y módulos.

import paq.subpaq.modulo

paq.subpaq.modulo.func()
Comentarios
  1. Hola! He estado leyendo la entrada y no he conseguido resolver un problema con la que estoy lidiando ahora mismo. Resulta que me he creado un módulo en el cual tengo algo como:

    def mimain():
    código …
    if __name__ == “__main__”:
    mimain()

    Pero cuando importo este modulo en otro programa, y este lo ejecuto desde consola se me ejecuta siempre el mimain() del módulo. ¿Hay alguna forma de que no se ejecute ese mimain dentro del otro programa que estoy lanzando?

    Gracias de antemano 😉

    Responder

  2. yense

    hola amigos bueno tengo un consulta de los modulos al importarlos

    ahora estoy trabajando con windows y bueno como saben que el instalador de python no viene con todos los modulos

    ahora mi pregunta es como agrego los demas modulos

    Responder

  3. yense, depende del módulo que quieras instalar. La mayoría tienen instaladores, otros tienes que instalarlos ejecutando su script setup.py.

    Responder

  4. María José

    hola! tengo una consulta que nadie me sabe responder, se puede poner la fecha y hora en la pantalla gráfica y que se vaya actualizando según el usuario utilice el programa? Gracias!

    Responder

  5. Javier Ortega

    Muchísimas gracias. Por fin he encontrado a alguien que me explique esto de los módulos de manera muy clara.

    Responder

  6. isma

    Hola!!! Me he creado una archivo union.py en el que defino uno clase link con varios metodos pero al importarlo en otro archivo visual.py al iniciar un objeto link: union.link(‘valores de inicio’) me da error: ‘module object has no atribute link’

    Responder

  7. cristhian

    buenas, estoy desarrollando un proyecto en pygtk y en estos dias me e encontrado con un pequeño problema el cual no estoy solucionando, tengo una ventana de acceso que permite ingresar el login y la contraseña, y despues abierto mi sistema abro otra ventana (factura), que para poder ver que usuario a comprado algo, tengo que conseguir de el valor que se ingreso como id del usuario al ingresar,,, como puedo hacer?? alguna idea??

    Responder

  8. cristhian

    en realidad se resume a como pasar valores de un .py a otro .py

    Responder

  9. Cristian, crea un objeto usuario donde almacenes los datos y que puedas compartir entre ambos py’s. El problema quizá sea de planteamiento. Un py principal, donde crees ese objeto usuario y desde él, lanzas la interfaz de usuario o lo que sea, pudiendo acceder a los datos de este objeto desde cualquier py posterior.
    Espero haberte aclarado algo.

    Responder

  10. RAM

    Muchas gracias por el aporte.

    Responder

  11. Hola,

    Excelente artículo, llevo poco tiempo con Python y la verdad es que tu explicación me ha sido especialmente útil.

    Muchas gracias!

    Responder

  12. Hola, estoy realizando una aplicación educativa y me interesa que todos los juegos de ésta rueden por el mismo frame. Esto me ha llevado a crear una clase frame demasiado larga.

    La pregunta es: ¿Es posible manipular un frame (dibujar en el,controlar eventos)desde un modulo exterior?

    Gracias

    Responder

  13. julian

    como puedo hacer esto estoy trabajando con python 3
    he seguido este manual y no he podido hacer esto:

    1.Importar un módulo estándar de Python para trabajar con fechas.

    2.Imprimir en pantalla la fecha actual en formato ISO 8601. Esto, usando la API del módulo importado.

    Responder

  14. JaviC

    No sé cuanto tiempo tendrá este articulo pero…

    ¿Hay alguna manera de mantener un directorio en la variable PYTHONPATH?

    es que yo hago lo de | import sys
    | sys.path.append(‘***’)

    y puedo cargar los ficheros que tengo ahí sin problemas, en cambio cuando cierro y vuelvo a abrir el interprete tengo que volver a hacerlo porque al consultar la variable no está el directorio que incluí

    Responder

  15. jimmy

    Hola que tal, antes que nada excelente aporte!!, apenas estoy adentrandome en la programacion con python.
    y me estaba preguntando es posible heredarle a una clase otra case que este dentro de un paquete?
    ej:
    clase: modulo\Calculadora.py
    clase: cientifica(Calculadora):
    ?
    saludos!, de antemano gracias 🙂

    Responder

  16. MARIELA

    Hola disculpe, soy nueva en python tengo un problema. Tengo un proyecto estructurado en diferentes carpetas,en cada uno de los arvhivos utilizo from sys import path,from os import getcwd
    path.append(getcwd() + “/..//models”),quiero ahorar lineas de codigo asi que he creado un archivo fuera de las carpetas con la clase con esa parte de codigo, hay alguna manera de hacer que cuando ejecute un determinado archivo ya este cargado la clase creado en otro archivo?

    Responder

  17. Andrés Peñaherrera

    Hola.

    Buscando una respuesta a este problema con mi tésis espero me ayuden por favor.

    Traceback (most recent call last):
    File “./gtables.py”, line 7, in
    from libs.SBTVD.Descriptors import *
    ImportError: No module named libs.SBTVD.Descriptors

    Responder

  18. yenu

    Hola
    Cree un modulo cuando lo voy a importar aparece un error

    Responder

  19. Juan

    Muchas gracias. El articulo facil y rápido que buscaba!

    Responder

  20. Xavier

    Favor quién puede ayudarme.. instale anaconda con la finalidad de trabajar en spyder-python 2.7 por lo cual quiero añadir en spyder mi propia librería ejemplo mj.py.. cuáles son los pasos a seguir..

    Responder

Deja un comentario