Persistencia de datos en la Raspberry Pi
Introducción
Durante el desarrollo de aplicaciones, la persistencia de los datos es un problema recurrente. En esta área, Python dispone de una larga lista de módulos para responder a diferentes exigencias: base de datos SQL, archivo plano, serialización y deserialización.
Serialización y deserialización con los módulos pickle y shelve
Serializar y deserializar de datos significa transformar una variable en una serie de bytes con el objetivo de transmitirla a través de la red y restaurar la serie, una vez transmitida, al otro lado de la conexión. Sin embargo, este mecanismo no implica necesariamente transmitir los datos a través de la red, sino que puede servir para congelar el estado de un programa en disco, para retomar más adelante este estado. La mayor parte de los lenguajes de programación deben ofrecer un juego de funciones en lo que respecta a la serialización de datos y Python no es una excepción a esta regla. La librería estándar ofrece dos módulos: pickle y shelve. Con el primero, el desarrollador es responsable de la manera en la que se serializan los datos. Mientras que el segundo ofrece una indexación de los datos serializados en forma de diccionario.
Serializar los datos puede realizarse directamente desde REPL:
>>> import pickle
>>> cadena = 'Hello world!'
>>> serial = pickle.dumps(cadena)
>>> print(serial)
b'\x80\x03X\x0c\x00\x00\x00Hello world!q\x00.'
>>> deserial = pickle.loads(serial)
>>> print(deserial)
Hello world!
Las estructuras de datos más habituales también son serializables:
>>> serial = pickle.dumps(dict(one='Hello', two='World'))
>>> print(serial)
b'\x80\x03}q\x00(X\x03\x00\x00\x00twoq\x01X\x05\x00\x00\x00Worldq\
x02X\x03\x00\x00\x00oneq\x03X\x05\x00\x00\x00Helloq\x04u.'
>>> type(serial)
<class 'bytes' >
>>> deserial = pickle.loads(serial)
>>> deserial['one'] ...
Tratar los archivos CSV con el módulo csv
CSV es un formato de datos muy popular, que se utiliza mucho, fundamentalmente para almacenar datos de texto en archivos planos. Este acrónimo (Comma Separated Value) describe lo que contiene un archivo CSV: campos de datos separados por comas. En realidad, la opción del carácter de separación puede ser arbitraria y diferente de una coma. Por razones históricas, la coma es la opción más habitual. En Python, la manipulación de un archivo CSV es posible gracias al módulo del mismo nombre, el módulo csv disponible en la librería estándar.
1. Creación y lectura de un archivo CSV
La creación se puede hacer de manera tradicional, es decir, a mano con un editor de texto o en Python, por medio del módulo. Se exponen dos interfaces de entrada/salida, respectivamente csv.reader y csv.writer. Para la escritura, será necesario utilizar la función csv.writer, que inicializa una interfaz de escritura en un archivo CSV. Recibe como parámetro un archivo abierto inicialmente y devuelve la interfaz que permite serializar los datos en el archivo en cuestión. Después de esta interfaz, la función writerow() serializa una lista o una tupla pasada como argumento. En este ejemplo, los datos se gestionan a través de la función generar_datos(), que devuelve una tupla de dos dimensiones. A continuación, esta estructura se recorre para serializarse en el archivo bdd/archivo.csv (Capitulo_10/csv_1.py):
1 #!/usr/bin/env python3
2 import csv
3
4 def generar_datos():
5 return (
6 ('Código', 'Nombre', 'Cantidad'),
7 ...
Manipular los datos XML con el módulo xml.etree.ElementTree
A continuación se muestra un formato muy popular en Internet para el intercambio de datos y que no necesita mayor presentación. Se trata del formato XML, acrónimo que significa eXtensible Markup Language y se define en la RFC 4825. XML es un formato que se inspiran en el lenguaje HTML y está principalmente destinado a estructurar el contenido más que a formatearlo, a diferencia de lo que sucede con el lenguaje HTML. Python incorpora un módulo para manipular datos XML que se conoce con el nombre de xml. La particularidad de este módulo es exponer no una librería, sino varias:
-
xml.dom, librería que se inspira en el framework DOM (Document Object Model);
-
xml.parsers que contiene un enésimo parser Expat;
-
xml.sax, otra librería para leer datos XML;
-
por último, xml.etree, la librería XML ElementTree.
Este capítulo se centra en la última librería de esta lista, a saber ElementTree.
1. Crear y serializar un archivo XML
La librería ElementTree expone varias clases y métodos para crear un archivo XML. Generalmente, la creación de un archivo XML pasa por formatear los datos en una cadena de caracteres. A continuación, esta cadena se convierte en un objeto XML para, finalmente, ser tratada por la librería y por último serializarse en un archivo. A continuación se muestra un ejemplo (Capitulo_10/xml_1.py):
1 #!/usr/bin/env python3
2 from xml.etree import ElementTree
3
4 def main():
5 ruta = 'bdd/solicitudes.xml'
6 print("Generación de '%s' ..." % (ruta))
7 xml = ElementTree.XML("""
8 <body>
9 <solicitudes>
10 <solicitud codigo="HP03" cantidad="2">
11 Impresora HP
12 </solicitud>
13 <solicitud codigo ="RP04" cantidad="4">
14 Raspberry Pi 1 versión B+
15 </solicitud>
16 ...
Gestión de una base de datos SQL ligera con el módulo sqlite3
SQL (Structured Query Language) es una herramienta imprescindible para la gestión de datos, principalmente gracias a las populares bases de datos MySQL y PostgreSQL, aparecidas al amparo del mundo del software libre, así como de las soluciones de gestión básicas de datos propuestas por Oracle. Muchos proyectos han visto la luz, como por ejemplo SQLite, principalmente destinados a los entornos embebidos y limitados en recursos. El principio de SQLite es sencillo: ofrecer una base de datos SQL ligera representada en forma de un archivo plano.
SQLite cubre las cuatro operaciones básicas, llamadas habitualmente CRUD:
-
Crear (Create)
-
Recuperar (Retrieve)
-
Actualizar (Update)
-
Eliminar (Delete)
El código que sirve de ejemplo para explicar este capítulo, no solo cubre el módulo sqlite3, sino también cmd, utilizado aquí con el objetivo de hacer que la aplicación sea interactiva y fácil de utilizar.
Presentación rápida del módulo cmd: este módulo forma parte de la librería estándar de Python, y aprovecha otro módulo para ofrecer una gestión avanzada del histórico y del autocompletado de comandos, el módulo readline. Aunque es poco conocido, este módulo es imprescindible cuando se trata de desarrollar rápidamente aplicaciones de consola. El siguiente ejemplo explica con detalle el desarrollo de una aplicación con cmd.
Como todas las aplicaciones que se han presentado en este libro hasta ahora, se comienza con la importación clásica de los módulos y la declaración de una clase en la que se compactará la lógica del programa (Capitulo_10/pisqlite.py):
1 #!/usr/bin/env python3
2 import sqlite3, cmd
3
4 class PiSQLite(cmd.Cmd):
Con el objetivo de que las funcionalidades ofrecidas por el módulo cmd puedan funcionar, la clase del programa en cuestión debe heredar de la clase cmd.Cmd. El principio es sobrecargar a continuación los elementos necesarios para el desarrollo de la aplicación. Comenzamos por el constructor de la clase:
5 def __init__(self, bajo):
6 cmd.Cmd.__init__(self)
7 self.prompt = '>> ' ...
Conclusión
Sin embargo, falta una última funcionalidad, olvidada de manera voluntaria durante la elaboración de este programa: la actualización de una entrada en la base de datos. Este ejercicio requiere la lectura de la documentación correspondiente al lenguaje SQL y se deja al lector como ejercicio.