Ir más lejos con Python
Introducción
El lenguaje Python tiene una librería estándar bien provista, que permite aligerar y simplificar el código sobre el procesamiento de tipos base, tipos complejos, procedimientos, etc.
Pero los intérpretes de Python llevan el concepto un paso más allá y llegan a integrar una gran variedad de librerías adicionales. Esta integración en el lenguaje base, permite realizar el despliegue de una aplicación mucho más rápido, pero también elimina el riesgo de incompatibilidad entre el lenguaje y una de estas librerías.
Estas librerías nativas permiten responder a las necesidades más habituales de un programa, cuyas interacciones con el exterior se multiplican (red, archivos, interfaz de usuario, etc.).
En este capítulo, discutiremos el uso de algunas de las librerías más utilizadas.
XML
1. Presentación
Utilizado tanto como soporte para protocolos de comunicación como para el almacenamiento de datos, el lenguaje XML es omnipresente en la informática moderna. Ofrece numerosas e indiscutibles ventajas que lo convierten en un formato muy popular (durabilidad, interoperabilidad, jerarquización de datos, establecimiento de una gramática, etc.). Es muy probable que un desarrollador, Python u otro, tarde o temprano se encuentre manipulando archivos XML en una aplicación.
Hay dos métodos principales para procesar archivos XML:
-
Poner completamente en memoria el archivo XML destino. Una vez en memoria, los datos, generalmente representados por una estructura de árbol, se pueden recorrer libremente utilizando los métodos adecuados. Esta técnica de tratamiento de archivos XML se denomina DOM (Document Object Model). DOM implica un uso de memoria proporcional al tamaño del archivo XML, ya que este se lee y se carga por completo. Esto le permite modificar fácil y directamente una parte específica de un archivo XML, pero en el caso de archivos demasiado grandes, la ocupación de memoria limitará su uso.
-
Leer en un flujo continuo el archivo sin almacenar nada y realizar el procesamiento a medida que se lee. Es posible que este método no sea adecuado si alguna vez se necesita examinar el archivo XML de forma no lineal. Este método se llama SAX (Simple API for XML). Al no almacenar el archivo en la memoria, le permite leer los flujos de archivos XML de cualquier tamaño, pero a costa de un procesamiento más complejo en caso de modificación de un segmento del archivo.
2. DOM
a. Lectura
Los intérpretes de Python tienen una implementación de analizador DOM llamada minidom. Esta permite implementar muy rápidamente la lectura de un archivo XML.
Tomemos una implementación de ejemplo de este módulo, leyendo el siguiente contenido XML:
<Coche nombre='delorean'>
<Propietario>Emmett Brown</Propietario>
<Equipamientos>
<Equipamiento tipo='Convector temporal' />
<Equipamiento tipo='Generador de fisión' />
</Equipamientos>
</Coche>
El primer paso será pedir al módulo...
JSON
JSON (JavaScript Object Notation) es un formato de intercambio de datos bastante minimalista, que se inspira, como su nombre indica, en la forma en que se representan los objetos en JavaScript:
var coche = {
modelo : "Delorean",
propietario : "Emmett Brown",
equipamientos : [{ equipamiento : { tipo : "Convector temporal" } },
{ equipamiento : { tipo : "Generador de fisión" } }]
}
El JSON, aunque tiene menos poder de expresión, es extremadamente útil para transmitir información "simple" como cadenas de caracteres, números enteros, tablas, etc. Elegir este formato puede ser aún más juicioso si tiene que ser leído por un sitio web que ha sido escrito o utiliza JavaScript, porque la transformación de estos datos en un objeto JavaScript es casi instantánea, ya que usa la misma notación que un objeto declarado por un desarrollador. Mientras que en XML debe analizar y transformar los datos, lo que requiere más tiempo de procesamiento.
Los casos de uso más frecuentes son la serialización de objetos Python en formato JSON y la deserialización de datos JSON en objetos Python. Python tiene por defecto una librería...
IHM
1. Tkinter
Hay una gran variedad de librerías en Python para desarrollar aplicaciones con interfaces gráficas. De hecho, las herramientas de creación de IHM más conocidas ofrecen una adaptación de su código a través para su uso en Python. Presente por defecto en casi todas las instalaciones de Python, la librería Tkinter es bastante minimalista y dispone de una representación gráfica bastante austera, teniendo en cuenta lo que se hace hoy día.
a. Creación de una ventana
Comencemos simplemente creando una ventana gráfica vacía, para una aplicación basada en una IHM.
Por supuesto, el punto de partida será la importación del módulo Tkinter. El componente gráfico (o widget) que puede contener otros se llama frame. Por lo tanto, es un frame lo que es necesario instanciar para obtener una ventana gráfica:
from tkinter import Frame
mi_ventana = Frame()
# Lanzamiento del bucle principal del IHM.
mi_ventana.mainloop()
Para un resultado más refinado:
La llamada del bucle principal de IHM es una llamada de bloqueo, es decir, la siguiente línea de código no se ejecutará hasta que se cierre la ventana. Este bloqueo permite a Tkinter tomar el control de la ejecución del proceso, para darle a la aplicación su carácter de orientación a eventos y esperar a que suceda algo para realizar el procesamiento (un clic en la cruz de cierre de la ventana, por ejemplo).
Es hora de personalizar aún más esta ventana. Para controlar mejor los aspectos de la ventana principal de la aplicación, es necesaria la creación de una clase heredada de Frame. De hecho, en lugar de cambiar los atributos del frame, también puede modificarlos directamente en el constructor. La ventaja es que, si alguna vez tiene que crear una segunda ventana (para mostrar las opciones del software, por ejemplo), ya tendrá los mismos atributos que la primera, lo que hace que la IHM sea más homogénea y, por lo tanto, menos molesta para el usuario.
from tkinter import Frame
class MiVentana(Frame):
# Cada widget tiene un primer parámetro de constructor
# que es su widget 'maestro', es decir, el que lo
# contiene....
Bases de datos
1. Presentación
Una base de datos es un software que permite almacenar, manipular y buscar información de forma optimizada e inteligente. El almacenamiento de información en un archivo XML, puede ser suficiente siempre que sea una pequeña cantidad de datos. Sin embargo, la búsqueda en un archivo puede ser ineficaz, ya sea en términos de tiempo de procesamiento (recorrido del árbol a través de SAX) o espacio de memoria (almacenar el árbol completo como en DOM). Además, una gran cantidad de datos almacenados en formato texto en un disco duro puede ocupar un espacio considerable, y el hecho de comprimirlos implica que en cada acceso, es necesario lanzar una descompresión, que aún lleva tiempo y usa más memoria.
El objetivo de una base de datos es precisamente resolver lo mejor posible todos estos problemas de almacenamiento, de uso de memoria (RAM o disco duro), de optimización de la búsqueda, etc. La configuración de una base de datos permite dar más importancia a una restricción particular. Por ejemplo, si la capacidad de respuesta de una aplicación es fundamental, será necesario configurar la base de datos para que optimice al máximo los accesos, lo que sin duda requerirá más espacio de memoria para almacenar más información, con el fin de acelerar la búsqueda. Si, por el contrario, el software se debe ejecutar en un espacio reducido en el disco, entonces la compresión debe estar al máximo, sabiendo que esto tendrá un impacto negativo en los tiempos de respuesta.
Hay muchos paradigmas de bases de datos, pero el más utilizado es el "relacional". Parecido a un diagrama de clases, la información se agrupa en "tablas" unidas por enlaces. Estas tablas se pueden asimilar a clases, donde cada columna es un atributo y cada fila es una instancia. El siguiente código produce datos que se podrían almacenar en una tabla de SuperHeroes:
class SuperHeroes:
def __init__(self, nombre, color, accesorio):
self.nombre = nombre
self.color = color
self.accesorio = accesorio
SuperHeroes("Tony Stark", "rojo", "armadura") ...
Multithreading
1. Presentación
Un thread, o literalmente un "hilo" (de ejecución), es una unidad de procesamiento dentro de un proceso. Un proceso puede contener varios thread, que luego se ejecutan en paralelo. La principal diferencia entre un conjunto de threads y un conjunto de procesos, es que cada uno de los procesos tiene su propia área de memoria, mientras que los threads del mismo proceso comparten una memoria común.
No es raro que la resolución de un problema de programación pase por una solución basada en el concepto de programación concurrente. De hecho, un software interactúa con muchos elementos y reacciona a muchos eventos que pueden ocurrir al mismo tiempo. Por ejemplo, un clic del ratón debe poder ser captado por un programa, pero al mismo tiempo, debe escuchar una interfaz de red mientras espera un mensaje, mientras se muestra un video y se reproduce la pista sonora. Establecer un paradigma de programación que pueda resolver el procesamiento en paralelo de diferentes tareas es, por lo tanto, mucho más lógico y eficiente. De hecho, encadenarlos uno tras otro implica evidentes riesgos de degradación de la reactividad de todos estos tratamientos (vídeo entrecortado, interfaz que no responde, etc.).
La práctica más común para tratar con múltiples tareas en lenguaje procedimental, es procesarlas una tras otra. Sin embargo, este enfoque no es el más elegante en la medida en que obliga a resolver secuencialmente problemas, que pueden surgir simultáneamente.
Tomemos el ejemplo de un coche al que debemos hacer tomar una curva, es decir que debemos hacerlo rodar mientras lo hacemos girar. El enfoque secuencial obligará a ejecutar la tarea "rodar" en un bucle y después la detendrá para ejecutar la tarea "girar", hasta que se complete el giro. Ejecutarlas muy rápidamente puede provocar la ilusión de que se realizan en paralelo, al igual que una rápida sucesión de fotografías puede dar la impresión de movimiento. Pero si la tarea "girar" acaba de bloquear el programa por una razón u otra (esperando la acción del usuario, error, cálculo demasiado largo, etc.), el coche ya no podrá rodar. Con el enfoque de una ejecución verdaderamente paralela, la ejecución...
Desarrollo web
1. Presentación
Hoy en día, Internet es una parte integrante de nuestras vidas y, como resultado, el desarrollo de aplicaciones que funcionan en la Web se ha convertido en una habilidad muy solicitada. En pocas palabras, una aplicación web consta de dos partes:
-
El "front-end", que es la parte "frontal" de la aplicación, es decir aquella manejada directamente por el usuario. Las tecnologías front-end son generalmente HMTL, JavaScript, AJAX, etc. Esta parte es generalmente dependiente del navegador web.
-
El "back-end", que es el "motor" de la aplicación. Esta parte es la que lleva a cabo el procesamiento pesado, como el almacenamiento de información en la base de datos, los largos cálculos a realizar, los diversos procesos necesarios para el funcionamiento de la aplicación. Los ejemplos típicos de lenguajes de back-end son PHP o ASP.NET.
Una de las dificultades de este tipo de desarrollo radica en la comunicación entre todas las capas involucradas:
-
el usuario escribe una URL en la barra del navegador;
-
se envía una petición a un servidor a través de Internet, para recibir la página que se va a mostrar;
-
algún servidor recibe y decodifica esta petición, luego inicia los algoritmos de generación de páginas;
-
estos tratamientos tienen buenas posibilidades de obtener información de una base de datos;
-
estos datos después se deben integrar en la generación de la página para ofrecer al usuario información personalizada (apellido, nombre, carrito de la compra actual, etc.);
-
Una vez generada la página, se debe enviar a la persona que la solicitó primero.
Navegador, capas de red, servidor, programa, base de datos, etc. Todas estas entidades son independientes y, por tanto, deben tener alguna forma de comunicarse entre sí. Uno de los problemas a los que se enfrentan las aplicaciones web es precisamente estas interfaces de comunicación, por las que circulan datos que deben ser decodificados de un lenguaje, para ser recodificados en otro.
Django es una herramienta de desarrollo web que se ocupa de buena parte de estos problemas de comunicación y homogeneiza gran parte de los distintos componentes de una aplicación web: todo está en Python y sigue la filosofía Modelo - Vista...