lunes, 31 de octubre de 2016

T1. MÓDULOS DE PYTHON: ARCHIVA Y EMPAQUETA TUS PROGRAMAS

CANTERA AL AIRE LIBRE EN LOS BARRANCOS (VALLES) DEL SUR DE ANAGA, EN LA VECINDAD DE SANTA CRUZ DE TENERIFE.

      Como hemos dicho, antes de comenzar a "batallar" con las funciones DEF (funciones definidas por el usuario, por el nombre de la sentencia, def, en Python), tenemos que conocer bien el tema de los módulos (modules) y, por extensión, el de los paquetes (packages) sin los cuales el acto de programación, por mera lógica, carece de sentido.
La organización del código que configura nuestro programa, igual que sucede con cualquier otro orden en nuestra vida real, como nuestro propio trabajo, la gestión de los ingresos dinerarios que entran a nuestro hogar o hasta una simple y placentera excursión al campo, la organización, decimos, es fundamental para poder mantenerlo de manera eficaz y poder utilizarlo en el tiempo para aquéllo para lo que lo hemos diseñado.
Del mismo modo que ocurre, pongamos por caso, en una empresa o firma comercial cualquiera donde cuanto más secciones, departamentos, filiales, etc... más importante y necesaria resulta mantenerlo todo bien organizado para que la mentada empresa o firma obtenga beneficios y se minimicen problemas de gestión, resulta básico mantener organizados los ficheros que forman parte de nuestros programas.
Para ayudarnos en esta cuestión Python nos proporciona dos unidades esenciales: los MÓDULOS ('modules', que vamos a ver a continuación) y los PAQUETES ('packages', que veremos más adelante).
¿Y qué es un módulo, ya que estamos?
Sucintamente, un módulo es cualquiera de los archivos *.py que creemos para reutilizar nuestros programas. Los módulos pueden ser también considerados como entidades que permiten la organización ("organización", concepto clave que, como vemos, reiteramos una y otra vez)  y una división lógica de nuestro código, como afirma Eugenia Bahit, Arquitecta de Software, Hacker especializada en tecnologías GLAMP (GNU/Linux, Apache, MySQL, Python y PHP) y Programadora Extrema, según refiere el blog blog.capacityacademy.com.
Vamos a estudiar mejor esta definición: un módulo de Python es un fichero codificado en este lenguaje, *.py, y que cumple dos roles fundamentales: por un lado, permite la reutilización o reusabilidad del código y, por otro, mantiene un espacio de nombres (namespace) de variables único.
Hacemos un inciso: reutilización y reusabilidad son dos conceptos sinónimos, significan exactamente lo mismo y forman parte del objetivo ideal de la programación orientada a objetos, la POO, por sus siglas en español, y que veremos en un nuevo blog más adelante. Y ya que estamos... ¿qué es eso de "reutilización"? Pues ni más ni menos que lo que da a entender la propia palabra: crear y guardar un fichero *.py que podemos utilizar  cada vez que queramos o, de manera modular, reimplantarlo en otro proyecto que afrontemos más adelante, ahorrando así tiempo y recursos porque, si ya disponemos de un módulo que hemos utilizado en un programa x, si nos resulta útil en un nuevo programa z que estemos diseñando, con las modificaciones necesarias si tiene que ser así... ¡caramba! ¿Por qué no importarlo (traerlo, llamarlo, invocarlo) y re-utilizarlo de nuevo?
Para profundizar en ello un poquito, que nunca está de más conocer mejor de lo que estamos hablando, vamos a ver cómo Python estructura el código: un script de Python tiene un punto de entrada para su ejecución (su ubicación concreta dentro de un programa. Recordemos que un programa puede estar  formado por un único script, por decenas de ellos, por centenares o, incluso, por miles entre los más complejos) que consta de varias sentencias (ver esquema en este mismo tutorial) y puede tener funciones definidas por el usuario (def) que serán invocados durante su ejecución.
Sin embargo, de acuerdo a  Arturo Fernández Montoro, autor del manual Python 3 al descubierto, de la editorial Anaya Multimedia, si tenemos definidos dos scripts diferentes, x y z, en uno de ellos, por ejemplo en el script que hemos llamado z podemos invocar a una o más funciones que nos puedan resultar útiles en z y que ya existan en x para no tener que volver a escribirlos (sobreescritura de código): esto es lo que, básicamente, se entiende por reutilización/reusabilidad del código.

ESCORRENTÍAS EN EL BOSQUE DE LAURISILVA DE ANAGA, NORESTE DE TENERIFE.
¿Y qué ocurre si tenemos definidas funciones con idéntico nombre en ambos scripts, en x y en z? Pues aquí es donde entra en juego el "espacio de nombres", el namespace de marras que henos mencionado antes, ya que cada fichero *.py es por sí mismo un módulo, recordémoslo, y como tal conserva la "unicidad" de su espacio.
Como mejor vamos a comprenderlo es con un ejemplo:
1.- En primer lugar creamos un fichero sencillito que vamos a llamar x.py, es decir, vamos a crear un módulo con el nombre x.py, y éste será su namespace: x.
                                                                                     
                                                                                            def say_hello():
                                                                                                   print("HOLA MUNDO")
                                                                                                   print("¿QUÉ TAL?")

* Recordemos que la construcción de funciones definidas por el usuario, def, las vamos a ver a continuación. Lo importante ahora es aprender y aprehender el concepto de módulo.
2.- A continuación vamos a crear un segundo fichero al que vamos a llamar z.py, es decir, vamos a crear un módulo con el nombre z.py, y éste será su namespace: z.

                                                                                             import x

                                                                                             x.say_hello()

3.- Ejecutamos, y el resultado será:

                                                                                             HOLA MUNDO
                                                                                             ¿QUÉ TAL?

Lo podemos ver perfectamente ilustrado en los siguientes ejemplos:




* En este caso hemos optado por cambiar nuestro IDLE habitual por otro, NINJA-IDE, simplemente por mostrar otras opciones posibles de IDES gratuitos a los que también es posible recurrir. Ya que contamos con algunas competencias en la codificación con Python, ¿por qué no atrevernos a probar algunos de los que existen y quedarnos con el que más nos guste?

Aún podemos añadir una nueva definición basada en la que nos ofrece el profesor don Jesús Conde: los módulos son los archivos que guardan o almacenan en su interior múltiples y diferentes funciones Python que no están disponibles de manera automática, como las funciones built-in, sino que hay que importarlas para poder hacer uso de las mismas en nuestros programas. Todas éstas, como scripts codificados en Python que son, llevan la extensión *.py.



UN  APUNTE RÁPIDO  SOBRE  LAS LIBRERÍAS DE PYTHON



      Tal y como apuntamos en el título, nuestra intención ahora mismo no es otra que la de ofrecer una cierta idea, una sinopsis aproximativa, más bien, de uno de los aspectos fundamentales de la programación: el uso (y recurso) de librerías, centrándonos en este caso en la nativa de Python. Hay autores que emplean el concepto de "librería estándar"  para referirse a la librería nativa de Python, la que se nos instala por defecto cuando descargamos el programa. A parte, existen también las llamadas "librerías de terceros", que engloban a todas aquellas librerías externas, creadas por programadores afines y/o solidarios con el proyecto  Python, y puestas a disposición pública para uso de cualquier otro programador, todos ellos módulos o conjuntos de módulos con extensión .py u otras extensiones, más restrictivas, asociadas al lenguaje Python como .pyw, .pyx, .pyd, etc.
Los módulos de Python, como sucede en las librerías nativas y/o estándares de la mayoría de los lenguajes de programación, se encuentran agrupadas bajo un epígrafe concreto que refiere un directorio específico que los acoge en tanto que ofrece funcionalidades comunes, relacionadas entre sí, y orientadas a un aspecto concreto de la "realidad" (p. ej., un módulo al que llamamos "áreas" que contiene un conjunto de funciones destinadas a calcular  el área de un triángulo (at.py), de un rectángulo (arect.py), de un círculo (acir,py), de un cilindro (acil.py), se un como (acon.py), de un pentágono (apen.py), etc.).
Cada módulo por sí mismo constituye, mutatis mutandis, un programa cerrado, completo, un script con toda la ley. Sin embargo, podemos dilucidar que un programa es algo que ha sido diseñado para ser ejecutado, mientras que un módulo es un constructo informático diseñado para ser importado, primero, y después, utilizado por un programador para ser ejecutado como parte de su programa.

                                                                                                   ******************



Para poder hacer uso de los módulos es necesario decirle a Python que queremos usarlos antes de poder importarlos. Son módulos que se alojan en la propia librería estándar de Python, esto es, como ya hemos dicho, la que se instala por defecto en la descarga del programa; aquéllos otros módulos que creamos nosotros mismos (funciones def) y, finalmente, los módulos creados o definidos por otros programadores que se alojan en librería externas o de terceros, a las que tenemos libre acceso desde internet o los módulos disponibles en los frameworks.
Ya, ya,...vale, pero...¿Cómo guardamos un archivo Python?
Buena pregunta.
Indudablemente, la forma más práctica y sencilla es hacerlo desde el propio IDLE de Python. Veámoslo paso a paso de manera esquemática:

1.- Creamos nuestro script:



2.- Dirigimos el cursor a la barra de menús del IDLE y hacemos clic sobre la pestaña "file":



3.- Una vez que tenemos abierto el menú desplegable de "file" pinchamos sobre la opción "new file":



4.- Se nos abre entonces un SHELL  secundario:



5.- Regresamos a nuestro SHELL primario, tan sólo haciendo haciendo clic sobre él, y hacemos una "copy" (copia) de nuestro script. Para hacerlo podemos hacerlo de dos maneras: la técnica, haciendo clic sobre la pestaña "edit" y después sobre la opción "Select All", con lo que se nos sombreará todo el área del SHELL. Tengamos en cuenta que cuando recurrimos a esta opción se nos va a copiar también el encabezado informativo del IDLE y todos los prompts de cada línea de código que luego tendremos que eliminar para que nuestro archivo *.py funcione correctamente.





O la opción manual, donde arrastramos el cursor por todo el SHELL cubriendo todo el bloque de código hasta dejarlo sombreado en gris. Esta área sombreada será la que copiemos: una vez tenemos nuestro script con sombra, hacemos clic con el botón derecho del ratón para que se nos despliegue un nuevo menú de opciones donde seleccionaremos la opción "copy". Esta opción es plausible con códigos cortos: evidentemente, con un SHELL con cientos o miles de líneas de código, la opción manual deviene inmanejable. Tengamos en cuenta que, como sucedía con la opción técnica, no tenemos por qué sombrear el encabezado informativo. Ni siquiera el primer prompt. Pero no así con los demás que, igualmente, tendremos que borrar.




6.- Regresamos al SHELL secundario por el mismo procedimiento de hacer clic sobre él y, haciendo de nuevo clic con el botón derecho del ratón, seleccionamos la opción "paste" (pegar) en el submenú desplegable:





7.- Una vez pasteado nuestro script en el SHELL secundario nos dirigimos a la barra de menús, pinchamos en "file" nuevamente, y en el desplegable, hacemos clic, esta vez, sobre la pestaña "Save As" para proporcionarle un nombre, el que deseemos, a nuestro archivo. La opción "Save" es recomendable usarla sólo cuando ya hemos creado nuestro archivo *.py y queremos guardar futuros cambios o modificaciones en el mismo.



8.- Se nos abre automáticamente el asistente de almacenamiento. Por defecto nos muestra arriba del todo la opción de guardar nuestro script en la carpeta matriz de Python, que suele tener un nombre como "Python 34", "Python 35", donde las dos cifras finales representan la versión del programa que tenemos instalado. Sin embargo, podemos elegir la  carpeta que queramos. Podemos crear, incluso, una carpeta específica que podríamos llamar "scriptspython", "módulospython", "módulosdelprograma_tal_o_cual", por ejemplo, para albergar en ella nuestros scripts. Deben ser carpetas a las que tengamos fácil acceso.

Abajo podemos ponerle el nombre que queramos. No es necesario que pongamos la extensión .py: Python lo hará de forma predeterminada por nosotros. Para nuestro ejemplo, elegimos el nombre "at".



Señalemos que en el instante de generar nosotros mismos un archivo con extensión .py, Python genera a su vez una copia del mismo a la que le aplica una extensión .pyc, donde la 'c' al final refiere la circunstancia de que la copia es una compilación a código c, el código-máquina de nuestro archivo *.py, lo que faculta al lenguaje para trabajar mucho más eficazmente. Existirán, pues, realmente, dos archivos 'at': uno at.py para nuestro propio "consumo", para hacérnoslo inteligible en tanto está transcrito bajo la sintaxis Python que conocemos y manejamos, y un segundo archivo at.pyc que resulta una copia del primero traducido al código máquina para ser utilizado exclusivamente por Python.

Apuntemos también que si cambiáramos el archivo at.py por otro, renombrándolo, por ejemplo, Python automáticamente anula el archivo at.pyc original y lo sustituye por uno nuevo en base al actual. 

9.- Al guardar, sobre el SHELL secundario aparecerá el nombre que le hemos proporcionado a nuestro módulo, en nuestro caso, recordemos, at.py:



10.- Para ejecutarlo, nos dirigimos de nuevo a la barra de menús y hacemos clic sobre "Run". En el desplegable, seleccionamos la última opción: "Run Module" que, si todo va bien, ejecutará el código, "correrá" el script:



11.- Al hacer clic sobre "Run Module", automáticamente, Python nos devuelve al SHELL primario y genera un "RESTART" con un nuevo prompt >>> que espera nuestra llamada al módulo.



12.- Si llamamos a la función y ejecutamos el script que hemos creado, Python nos devuelve el resultado. Esto significa que nuestro módulo ha sido correctamente almacenado, pudiendo el intérprete de Python reconocerlo (por la extensión del fichero) y acceder a él de forma rápida y eficaz.



Podemos continuar añadiendo scripts a nuestro módulo dese el SHELL secundario, aprovechando que tenemos el módulo abierto, y sin necesidad de apoyarnos en prompts. Bien es cierto que esto, en el IDLE de Python, resulta un tanto limitado como ya experimentaremos en su momento, por lo que para estas cuestiones quizás fuera mejor contar con un IDE dedicado o con un editor de código más avanzado.

Para ilustrarlo con un ejemplo, escribimos una nueva función directamente sobre el SHELL secundario que nos permite calcular el perímetro de un triángulo dado sus tres lados. Una vez hemos codificado la función, la guardamos tal cual hemos aprendido a hacerlo, y clicamos sobre "Run Module" de cara a que se genere un "Restart Shell" en el SHELL primario. Podemos observar que ambas funciones corren de manera adecuada.




      Os voy a ladrar un secreto, que me he enterado yo, dándole con la pata al teclado. Es posible construir un código perfectamente funcional y guardarlo como un módulo Python de manera directa en nuestro humilde Bloc de Notas de Windows. ¡Sí! Tan sólo tenemos que construir nuestro código tranquilamente, eso sí, respetando las indentaciones o sangrías, bien manteniendo los cuatro espacios de rigor propuestos en la convención PEP8, o bien pulsando sobre la tecla de tabulación ↹. Cuando hayamos terminado, le damos un nombre a nuestro archivo, con la extensión .py y lo guardamos en la carpeta en la que queramos. Así se nos genera un archivo Python que podemos runear cuando queramos. Veamos cómo hacerlo:















Pues bien, ahora que ya hemos aprendido a crear y guardar módulos como Python manda, veremos en la siguiente entrada cómo importarlos para integrarlos en nuestros programas más complejos.

FLORACIÓN DEL BREZO EN EL MONTEVERDE DE LAS LADERAS DEL PUERTO DE ERJOS, NORTE DE TENERIFE.