domingo, 14 de febrero de 2010

MySQL y Python - Relación de pura potencia I

No creo que en este momento en el que nos encontramos haya alguien que no haya oido hablar del sistema gestor de bases de datos MySQL.

Prácticamente todo el mundo conoce este sistema y lo relaciona junto con los paquetes de software Apache (servidor) y PHP (lenguaje de script para creación de páginas web). Y en cierto sentido es así, ya que este SGBD se ha hecho muy popular por su gran rendimiento y por su escaso coste. No hace mucho MySQL fue adquirido por Sun, y ahora no se bien como está el tema de licencias. Como cabe esperar, para empresas que quieran soporte y cosas de esas habrá un MySQL de pago. De todas formas MySQL sigue siendo software libre, y vamos a hablar en este post sobre él y la magnífica relación que mantiene con Python, mediante el módulo MySQLdb (creado por Andy Dustman).

Antes de empezar supongo que todos sabemos lo que es una base de datos, lo que es un cursor, tablas, campos, selects, inserts, .... y un largo etcétera. Yo no soy ningún experto en bases de datos, pero si un fan de MySQL, por varios motivos: es gratuito, muy potente, ligero, fácil de configurar e instalar, soporta transacciones (y bloqueo de registros e integridad referencial mediante InnoDB), y en español!!!.

Podemos descargarnos el SGBD MySQL desde su página web, http://www.mysql.com/. Además, también puede interesarnos ciertas herramientas para trabajar con este sistema gestor, como son:

- MySQL GUI Tools: Paquete de tres herramientas gráficas para facilitar el uso de MySQL: MySQL Administrator 1.2 (consola de administración gráfica), MySQL Query Browser 1.2 (para crear, ejecutar y optimizar consultas SQL) y MySQL Migration Toolkit 1.1 (para migrar esquemas y datos desde varias bases de datos relacionales -Oracle, Microsoft SQL Server, Microsoft Access, etc.- a MySQL 5.0 o posterior).

- MySQL WorkBench: Herramienta de diseño de bases de datos para MySQL. Se pueden crear y editar objetos tales como tablas, rutinas y vistas y su representación visual en la pantalla permite comprender fácilmente y trabajar eficientemente con esquemas de bases de datos complejos y simples (antes de instalar MySQL WorkBench, se necesita tener instalado .NET Framework 2.0).


- phpMyAdmin: Herramienta escrita en PHP 5.2 (o posterior) para la administración de MySQL 5.0 (o posterior) a través de la web (si por cualquier razón se tuviera instalado Apache y PHP).

También podemos encontrarnos MySQL en ciertos "paquetes integrados" para la programación en web, como Instant Rails 2.0 (es un paquete que instala Ruby, Rails, Apache y MySQL y permite crear aplicaciones Ruby on Rails en un entorno autónomo), EasyPHP 5.3.0 (paquete que combina Apache 2.2.13, MySQL 5.1.37 y PHP 5.3.0. También incluye phpMyAdmin), AppServ 2.5.10 (paquete que combina Apache 2.2.8, MySQL 5.0.51b y PHP 5.2.6. También incluye phpMyAdmin 2.10.3), Uniform Server 5.5.a (paquete con Apache 2.2.14, MySQL 5.1.41 y PHP 5.2.12. Este paquete está configurado para un entorno de producción), WampServer 2.0.i (paquete que combina Apache 2.2.11, MySQL 5.1.36 y PHP 5.3.0. También incluye PECL, SQLitemanager y phpmyadmin.) ó XAMPP 1.7.3 (paquete que combina el servidor Apache 2.2.14, la base de datos MySQL 5.1.41 y el lenguaje de programación PHP 5.3.1. También incluye PEAR, Perl, mod_php, mod_perl, mod_ssl, OpenSSL, phpMyAdmin 2.11.9.2, Webalizer, Mercury Mail Transport System para Win32 y NetWare Systems, JpGraph, FileZilla FTP Server, mcrypt, eAccelerator, SQLite, y WEB-DAV + mod_auth_mysql. Este paquete está configurado para un entorno de desarrollo, no de producción.) Evidentemente habrá muchos otros más, aquí es solo un pequeño ejemplo de lo extendido que está MySQL y de sus posibilidades, especialmente la relación que mantiene con PHP.

Antes de empezar cabe decir que lo que vamos a comentar aquí es para las versiones de MySQL 5 y posteriores. La versión de Python que utilizo es la 2.5.4 y la versión 1.2.2 de MySQLdb.

MySQL y Python... ¿cómo?... la culpa la tiene la alcahueta de MySQLdb.

Python es un lenguaje orientado a objetos que usa módulos que se importan y utilizan en los programas que escribimos. Hay un módulo, que podemos descargar de http://sourceforge.net/projects/mysql-python/, llamado MySQLdb, que sirve para poder conectar una aplicación Python a un sistema gestor MySQL. Este módulo permite a los programadores hacer de todo, a saber, ejecutar comandos SQL, recoger el resultado de consultas SQL en un formato de lo más simple (una tupla de tuplas, esto es, una tupla de filas), y demás, de una manera muy fácil y sencilla.

Para trabajar con este sistema basta tener instalado Python, MySQL y el módulo MySQLdb. Opcionalmente, si quieres hacer o crear fácilmente bases de datos y tablas para usarlos con los ejemplos te recomiendo un administrador, tal como PHPMyAdmin (si tienes Apache y PHP) ó MySQL Administrator (si solo tienes instalado el MySQL). Pero hay que tener claro que aquí se habla de MySQL y Python, relacionándose con el módulo MySQLdb.

Para saber de métodos y atributos del módulo MySQLdb, una vez descargado podemos irnos a la documentación de Python e investigar un poco. Esto es:

En esta ayuda se nos detallan todas las clases que tiene, sus métodos, parámetros y demás. Si necesitas algún tipo de ayuda o quieres saber más sobre las características de MySQLdb, mira aquí. Por ejemplo, para la clase cursor podemos ver los métodos que tiene, y su explicación:

Yo he instalado MySQL, con usuario root y clave de acceso 1234. Evidentemente no es lo apropiado, pero para aprender basta.

Creamos una base de datos, llamada pruebas_python, con una tabla, cliente, y ciertos campos para usarla de conejillo de indias.


Por último insertamos ciertas filas en la tabla...

Bueno.... ya hemos visto mucho de MySQL. Viendo las capturas de pantalla nos damos una idea de lo que vamos a utilizar (datos de conexión, tablas, campos, información de campos). Ahora entramos en Python. Tenemos instalado MySQLdb. Comenzamos!

Conexión a la base de datos.

Importamos el módulo MySQLdb y creamos un objeto conexión, mediante los parámetros
específicos para poder conectar con la base de datos pruebas_python.


import MySQLdb

try:
conexion = MySQLdb.connect(host = "localhost", \
user = "root", passwd = "1234",db = "pruebas_python")
print "Conexión realizada"
except:
print "Error en conexión"


También podría habernos interesado crear la conexión sin especificar la base de datos, esto es:

conexion = MySQLdb.connect(host = "localhost", user = "root", passwd = "1234")

Una conexión correcta devuelve un objeto conexión, el cual se puede utilizar para crear un cursor. Un cursor es necesario para ejecutar una sentencia SQL y para recuperar el resultado generado por consultas.

cursor = conexion.cursor()

Recuperación de información: SELECT.

En MySQLdb hay varias formas de recuperar información, dependiendo del método que utilicemos a la hora de recuperar las filas (después de lanzar la sentencia SQL select):

1) Mediante el método fetchall. Mediante este método se nos devuelven todas las filas del resultado de hacer el select. El formato en el que se nos da es una tupla de tuplas, donde cada tupla es una fila del resultado.

Ejecutamos sentencia SQL select:

cursor.execute("SELECT * FROM cliente")

Recuperamos las filas (que están en el servidor) resultado de la sentencia select:

ret = cursor.fetchall()

Y las sacamos por pantalla.

print ret

Dando el siguiente resultado:

((1L, '\xc1ngel', 'Lorca'), (2L, 'H\xe9ctor', 'La Uni\xf3n'), (3L, 'Juan Mar\xeda', 'Los Belones'), (4L, 'Mar\xeda', 'La Uni\xf3n'), (5L, 'Fernando', 'Murcia'), (6L, 'Ana', 'Murcia'), (7L, 'Dori', 'Los Belones'), (8L, 'Emilia', 'El Llano del Beal'), (9L, '\xc1ngel', 'El Estrecho'), (10L, 'Naomi', 'Los Belones'), (11L, '\xc1lvaro', 'Lorca'), (12L, 'Gabriela', 'Barcelona'))

Como vemos, es una tupla de tuplas, es decir, una tupla que contiene un conjunto de tuplas, en donde cada elemento del conjunto es un fila del resultado del select definido en el método execute del cursor. Podemos mejorar la salida:


print "Listado de clientes"
print "-------------------"
for fila in ret:
print str(fila[0]), " - " , str(fila[1]).strip(), " (", str(fila[2]).strip(), ")"

Y para ver la potencialidad que tenemos a la hora de recoger los datos del select, mira el siguiente código:

i = 0
for fila in ret:
for campo in range(0,len(fila)):
print "Dato en coord. (i = ",str(i),", j = ",str(campo),"): ",fila[campo]
i = i + 1


Y el resultado que da:

Posición en coordenadas (i = 0 , j = 0 ): 1
Posición en coordenadas (i = 0 , j = 1 ): Ángel
Posición en coordenadas (i = 0 , j = 2 ): Lorca
Posición en coordenadas (i = 1 , j = 0 ): 2
Posición en coordenadas (i = 1 , j = 1 ): Héctor
Posición en coordenadas (i = 1 , j = 2 ): La Unión
Posición en coordenadas (i = 2 , j = 0 ): 3
Posición en coordenadas (i = 2 , j = 1 ): Juan María
Posición en coordenadas (i = 2 , j = 2 ): Los Belones
Posición en coordenadas (i = 3 , j = 0 ): 4
Posición en coordenadas (i = 3 , j = 1 ): María
Posición en coordenadas (i = 3 , j = 2 ): La Unión
Posición en coordenadas (i = 4 , j = 0 ): 5
Posición en coordenadas (i = 4 , j = 1 ): Fernando
Posición en coordenadas (i = 4 , j = 2 ): Murcia
Posición en coordenadas (i = 5 , j = 0 ): 6
Posición en coordenadas (i = 5 , j = 1 ): Ana
Posición en coordenadas (i = 5 , j = 2 ): Murcia
Posición en coordenadas (i = 6 , j = 0 ): 7
Posición en coordenadas (i = 6 , j = 1 ): Dori
Posición en coordenadas (i = 6 , j = 2 ): Los Belones
Posición en coordenadas (i = 7 , j = 0 ): 8
Posición en coordenadas (i = 7 , j = 1 ): Emilia
Posición en coordenadas (i = 7 , j = 2 ): El Llano del Beal
Posición en coordenadas (i = 8 , j = 0 ): 9
Posición en coordenadas (i = 8 , j = 1 ): Ángel
Posición en coordenadas (i = 8 , j = 2 ): El Estrecho
Posición en coordenadas (i = 9 , j = 0 ): 10
Posición en coordenadas (i = 9 , j = 1 ): Naomi
Posición en coordenadas (i = 9 , j = 2 ): Los Belones
Posición en coordenadas (i = 10 , j = 0 ): 11
Posición en coordenadas (i = 10 , j = 1 ): Álvaro
Posición en coordenadas (i = 10 , j = 2 ): Lorca
Posición en coordenadas (i = 11 , j = 0 ): 12
Posición en coordenadas (i = 11 , j = 1 ): Gabriela
Posición en coordenadas (i = 11 , j = 2 ): Barcelona

Como se puede observar, esto da bastante juego, sobretodo a la hora de presentar la información resultante.

3 comentarios:

  1. Hola Angel,

    Tus posts son de mucha ayuda, puedo decir que me han servido de mucho, al momento estoy realizando una aplicación con snmp y el post de BD me ayudado mucho en este mini-desarrollo.

    Gracias!

    ResponderEliminar
  2. gracias deberás lo necesitaba

    ResponderEliminar
  3. Hasta ahora no he encontrado una nueva herramienta genial para trabajar con MySQL - Valentina Studio. Es la edición gratuita puede hacer las cosas más de las muchas herramientas comerciales!
    ¡Muy recomendable comprobarlo. http://www.valentina-db.com/en/valentina-studio-overview

    ResponderEliminar