# Módulos y ejecución Hasta ahora, has ejecutado el código en la REPL y de vez en cuando has usado `F5` en IDLE para ejecutar. Aunque te ha permitido salir del paso, necesitas saber más en detalle cómo funciona la ejecución para empezar a hacer tus programas. Además, es absurdo que te pelees contra todo, hay que saber qué batallas librar, así que necesitarás aprender a importar código realizado por otras personas para poder centrarte en lo que más te interesa: resolver tu problema. Este capítulo trata ambas cosas, que están muy relacionadas, y sirve como trampolín para el siguiente, la instalación de nuevos paquetes y la gestión de dependencias, y los posteriores sobre librerías interesantes que te facilitarán el desarrollo de tus proyectos. Este capítulo ya te capacita casi al cien por cien para la programación aunque aún no hemos trabajado su utilidad, pero seguro que alguna idea se te habrá ocurrido, si no no estarías leyendo este documento. ## Terminología: módulos y paquetes En python a cualquier fichero de código (extensión `.py`) se le denomina *módulo* (*module*). A cualquier directorio que contenga módulos de código python y un fichero llamado `__init__.py`, que puede estar vacío, se le denomina *paquete* (*package*). El uso del fichero `__init__.py` permite que python busque módulos dentro del directorio. Piensa en los paquetes como grupos de módulos que incluso pueden anidarse con subpaquetes. En la documentación oficial verás en más de una ocasión que se trata a los paquetes como si fueran módulos, y tiene cierto sentido, porque, normalmente, existe un módulo principal que permite el acceso a un subpaquete. Así que, principalmente estás trabajando con un único módulo de un paquete, que contiene subpaquetes a los que este módulo hace referencia. Aunque pueda sonar algo enrevesado, no te preocupes por ahora: los módulos son ficheros únicos y los paquetes conjuntos de ellos. ## Ejecución Ya conoces un par de maneras de ejecutar tus módulos de python. Usar la REPL, introduciéndole el código que quieres ejecutar, llamar a la función «ejecutar módulo» de IDLE con la tecla `F5` e incluso llamar a la shell de sistema con un comando similar a este: ``` bash python mi_archivo.py ``` Normalmente, los ficheros de python se ejecutan de este último modo en producción, mientras que los dos anteriores son más usados a la hora de desarrollar. Realmente son métodos similares, en todos ellos el intérprete accede al fichero o contenido que recibe y ejecuta las líneas una a una. Existe también una opción adicional muy usada que sirve para ejecutar módulos que el sistema sea capaz de encontrar por sí mismo, en lugar de indicarle la ruta, se le puede indicar simplemente el nombre del módulo usando la opción `-m`: ``` bash python -m nombre_de_modulo ``` ## Importación y *namespaces* Anteriormente hemos pasado sobre la sintaxis de la importación de forma muy superficial pero tampoco es mucho más compleja a lo que ha aparecido. La sentencia `import` permite importar diferentes módulos a nuestro programa como en el siguiente ejemplo: ``` python >>> import datetime >>> datetime ``` Han pasado, sin embargo, muchas cosas interesantes en el ejemplo. En primer lugar, python ha buscado y encontrado el módulo `datetime` en el sistema y, en segundo lugar, ha creado un objeto módulo llamado `datetime` que atesora todas las definiciones globales del módulo `datetime`. Empezando por el final, python usa lo que se conoce como *namespace* de forma muy extendida. Los *namespaces*, de nombre (*name*) y espacio (*space*), son una herramienta para separar contextos ampliamente usada. Los objetos, en realidad, son una caso de *namespace* ya que cuando se llama a un método se le dice cuál es el contexto de la llamada, es decir: al método de qué objeto se llama. Para los módulos el proceso es el mismo. La sentencia `import` trae un módulo al programa pero lo esconde tras su *namespace*, de este modo, para acceder a algo definido en el recién importado módulo es necesario indicarle el nombre de éste de la siguiente manera: ``` python >>> import datetime >>> datetime.date.today() datetime.date(2019, 12, 3) ``` En el ejemplo se accede a la clase `date` dentro del módulo `datetime`, y se lanza su función `today`, que indica el día de hoy. Como puedes apreciar, el operador `.` se utiliza del mismo modo que en las clases y objetos, y en realidad es difícil saber cuándo se está accediendo a una clase y cuándo a un módulo, aunque tampoco es necesario saberlo. Para no tener que escribir el nombre del módulo completo, existe otra versión de la sentencia `import` que tiene un comportamiento muy similar: ``` python >>> import datetime as dt >>> dt.date.today() datetime.date(2019, 12, 3) ``` En este ejemplo, se ha cambiado el nombre del módulo a uno más corto decidido por el programador, `dt`. El funcionamiento es el mismo, simplemente se ha cambiado el nombre para simplificar. Este cambio de nombre también es útil cuando se va a importar un módulo cuyo nombre es igual que alguna otra definición. Cambiando el nombre se evitan colisiones. Existen versiones además, que permiten importar únicamente las funciones y clases seleccionadas, pero que las añaden al *namespace* actual, para evitar tener que usar el prefijo. ``` python >>> from datetime import date >>> date.today() datetime.date(2019, 12, 3) ``` En este último ejemplo, se trae la clase `date` al contexto actual. También existe la posibilidad de importar más de una definición del módulo, usando la coma para separarlas, o todo lo que el módulo exponga mediante el símbolo `*`. Es peligroso, sin embargo, traer definiciones al namespace actual de forma descuidada, sobre todo con la última opción, porque es posible que se repitan nombres por accidente y se pisen definiciones. Los namespaces se inventan con el fin de separar las definiciones y evitar colisiones de este tipo. ### Búsqueda Una vez descrito cómo se interactúa con los módulos importados, es necesario describir dónde se buscan estos módulos. Los módulos se buscan en los siguientes lugares: 1. El directorio del fichero ejecutado o el directorio de trabajo de la REPL 2. Los directorios indicados en el entorno 3. La configuración por defecto (depende de la instalación) Esto significa que si guardas un archivo de python en IDLE y guardas otro más en el mismo directorio con el nombre `modulo.py` podrás importarlo usando `import modulo` en el primero, ya que comparten directorio. Lo mismo ocurre con los paquetes, crear un directorio con nombre `paquete` y añadirle un fichero vacío llamado `init.py` te permitirá hacer `import paquete`. Si añadieras más módulos dentro del paquete, podrías importar cada uno de ellos mediante `paquete.modulo`. > Los nombres de los ficheros deben coincidir con el el nombre del módulo > más la extensión `.py`. En el caso de los directorios, saltar a un > subdirectorio implica acceder a un paquete, por lo que se añadirá un punto > (`.`). El primer punto sirve para facilitar que organices tu proyecto de python en varios módulos, separando así la funcionalidad en diferentes archivos. Los últimos dos puntos son los que permiten a python encontrar su librería estándar y los módulos de sistema. El tercero depende de la instalación y del formato de ésta: si python está instalado como portable no será igual que si se instala en el sistema del modo habitual. El segundo punto también puede variar de un sistema a otro, pero en resumen se trata de varias variables de entorno de sistema que le indican a python dónde buscar (normalmente toman el nombre `PYTHONPATH`, pero no es siempre así). El segundo punto puede alterarse de modo que en función de lo que se le indique, se puede pedir a python que busque los módulos en un lugar u otro. Estos lugares de búsqueda se pueden mostrar de la siguiente manera: ``` python >>> import sys >>> print(sys.path) [ '', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages'] ``` En función del sistema en el que te encuentres y la configuración que tengas, python mostrará diferente resultado. Rescatando un ejemplo previo: ``` python >>> import datetime >>> datetime ``` Ahora entiendes por qué es capaz de encontrar `datetime` en `/usr/lib/python3.6`, carpeta listada en `sys.path`, bajo el nombre `datetime.py`. ## Ejecución e importación A la hora de importar un módulo, python procesa el contenido de éste ya que necesita definir las funciones, clases, valores, etc. a exportar. Para poder hacerlo, python necesita ejecutar el módulo. Python define una forma de separar la funcionalidad del código de sus definiciones con el fin de poder crear código cuyas definiciones sean reutilizables mediante la importación en otro módulo, sin que tenga ninguna funcionalidad cuando esto ocurra, pero habilitando que tenga funcionalidades cuando sea llamado directamente. Un ejemplo de uso de esto puede ser un módulo de acceso a ficheros, por ejemplo, que visualice el contenido del fichero cuando se llame de forma directa pero que cuando se importe únicamente aporte las funciones de lectura y escritura sin leer y mostrar ningún fichero. Para que los módulos puedan tener esta doble vida, python define la variable `__name__` que representa en qué nivel del *scope* se está ejecutando el módulo actual. La variable `__name__` toma el valor del nombre del módulo cuando éste está siendo importado y el valor `__main__` cuando ha sido llamado de forma directa o está siendo ejecutado en la REPL. `__main__` es el *scope* global de los programas, por lo que cuando algo se declara en él, implica que es el programa principal. Para poder diferenciar cuándo se ha ejecutado un módulo de forma directa y cuando se ha importado se utiliza lo que se conoce como `__main__` *guard*: ``` python if __name__ == "__main__": # Este bloque sólo se ejecuta cuando el módulo es el principal ``` Aunque igual es un poco incómodo de entender de primeras, encontrarás esta estructura en casi cualquier módulo de código python. Se utiliza constantemente, incluso para los casos en los que no se pretende que el código pueda importarse. Es una buena práctica incluir el *guard* para separar la ejecución de las definiciones, de este modo, quien quiera saber cuál es la funcionalidad del módulo tendrá mucho más fácil la búsqueda. Puedes leer más sobre este tema en la documentación de python[^main-guard]. [^main-guard]: Siguiendo este concepto, también existe el un estándar de nomenclatura de ficheros. El nombre `__main__.py` hace referencia al fichero que contiene el código principal del programa y será el fichero que python buscará ejecutar siempre que se le pida ejecutar un paquete o un directorio sin especificar qué módulo debe lanzar. Por ejemplo, ejecutar `python .`[^dot] en la shell de sistema es equivalente a ejecutar `python __main__.py`. [^dot]: `.` significa directorio actual en cualquiera de los sistemas operativos comunes. ## Lo que has aprendido En este capítulo corto has aprendido lo necesario sobre importación de módulos y ejecución de código. Conocer en detalle el patrón de búsqueda de módulos de python es primordial para evitar problemas en el futuro y organizar los proyectos de forma elegante. Además, el `__main__` *guard* era una de las últimas convenciones de uso común que quedaban por explicar y una vez vista ya eres capaz de leer proyectos de código fuente que te encuentres por ahí sin demasiados problemas. Los próximos capítulos, basándose en lo aprendido en éste, te mostrarán cómo instalar nuevas dependencias y cómo preparar tu propio código para que pueda ser instalado de forma limpia y elegante.