domingo, 13 de mayo de 2018

Bases de datos MySQL (y MariaDB) con PyMySQL




MySQL es un popular sistema de gestión de bases de datos multiplataforma de tipo relacional que proporciona un excelente rendimiento, seguridad y flexibilidad.

MySQL lo utilizan en infinidad de empresas y desde hace años es uno de los productos estrellas en el juego de herramientas LAMP para servidores y aplicaciones web.

Por su parte Python, debido a su carácter todoterreno, es una de las opciones para trabajar con MySQL y algunos frameworks basados en este lenguaje, como Django o Pyramid, soportan también esta base de datos. MySQL da soporte a aplicaciones muy conocidas de Internet: desde la Wikipedia a las redes sociales Reddit, Twitter, Youtube... y muchos más.

En la sección de anexos de Python para impacientes hemos incluido una Guía urgente de MySQL con información esencial para un programador Python para instalar MySQL en un servidor GNU/Linux Debian/Ubuntu y operar con una base de datos desde el Shell. La base de datos personal que se utiliza en los ejemplos de la guía es la que vamos utilizar también en los ejemplos de este artículo. Si no tienes experiencia con MySQL recomendamos la realización de los ejemplos que se proponen en dicha guía.

A continuación, contando la infraestructura necesaria instalada, con MySQL funcionando, vamos a mostrar varios ejemplos que utilizan el paquete Python PyMySQL para conectarse y operar con la base de datos personal de la mencionada guía.

PyMySQL es un paquete desarrollado por el japonés Yutaka Matsubara que permite trabajar tanto con bases de datos del gestor MySQL como de MariaDB, un derivado del primero con licencia GPL que utiliza los mismos comandos, interfaces, APIs y bibliotecas.


Instalar PyMySQL con PIP


Para instalar el paquete PyMySQL:

$ pip install pymysql


Conectar con base de datos y obtener datos de una tabla


El siguiente ejemplo muestra cómo conectar con PyMySQL con la base de datos personal y leer todos los registros de la tabla Usuarios:

import pymysql

# Conectar con base de datos
conexion = pymysql.connect(host="localhost", 
                           user="alejandro", 
                           passwd="2018_alejandro", 
                           database="personal")
cursor = conexion.cursor()

# Recuperar registros de la tabla 'Usuarios'
registros = "SELECT * FROM Usuarios;"

# Mostrar registros
cursor.execute(registros)
filas = cursor.fetchall()
for fila in filas:
   print(fila)

# Finalizar 
conexion.commit()
conexion.close()


Añadir una tabla nueva


Este ejemplo muestra el modo de agregar una tabla llamada Oficinas a la base de datos personal con PyMySQL.

import pymysql

# Conectar con base de datos
conexion = pymysql.connect(host="localhost", 
                           user="alejandro", 
                           passwd="2018_alejandro", 
                           database="personal")
cursor = conexion.cursor()

# Agregar nueva tabla 'Oficinas' a la base de datos 'personal'
TablaOficinas = """CREATE TABLE Oficinas(
denom CHAR(20),
provin CHAR(10),
PRIMARY KEY (denom))"""

cursor.execute(TablaOficinas)
print("Se ha agregado la tabla 'Oficinas' a la base de datos")

# Cerrar conexión
conexion.close()


Insertar registros en la tabla nueva


En el código siguiente se insertan tres registros en la tabla Oficinas.

import pymysql

# Conectar con base de datos
conexion = pymysql.connect(host="localhost", 
                           user="alejandro", 
                           passwd="2018_alejandro", 
                           database="personal")
cursor = conexion.cursor()

# Definir comandos para insertar registros
registro1 = "INSERT INTO Oficinas VALUES ('Central', 'Sevilla');"
registro2 = "INSERT INTO Oficinas VALUES ('Norte', 'Bilbao');"
registro3 = "INSERT INTO Oficinas VALUES ('Extremadura', 'Badajoz');"

# Ejecutar comandos
cursor.execute(registro1)
cursor.execute(registro2)
cursor.execute(registro3)

# Finalizar transacción y cerrar
conexion.commit()
conexion.close()


Mostrar tablas y obtener datos de la tabla nueva


En el siguiente ejemplo se listan las tablas de personal y los registros de la tabla Oficinas.

import pymysql

# Conectar con base de datos
conexion = pymysql.connect(host="localhost", 
                           user="alejandro", 
                           passwd="2018_alejandro", 
                           database="personal")
cursor = conexion.cursor()

# Recuperar registros de la tabla 'Oficinas'
tablas = "SHOW TABLES;"
registros = "SELECT * FROM Oficinas;"

# Mostrar tablas
cursor.execute(tablas)
filas = cursor.fetchall()
print("Tablas de 'personal':")
for fila in filas:
   print(fila)

# Mostrar registros
cursor.execute(registros)
filas = cursor.fetchall()
print("Registros de 'Oficinas':")
for fila in filas:
   print(fila[0], ":", fila[1])

# Finalizar 
conexion.commit()
conexion.close()


Borrar una tabla


Por último, un ejemplo para borrar la tabla Oficinas de la base de datos.

import pymysql

# Conectar con base de datos
conexion = pymysql.connect(host="localhost", 
                           user="alejandro", 
                           passwd="2018_alejandro", 
                           database="personal")
cursor = conexion.cursor()

# Construir comando para borrar tabla
BorrarTabla = "DROP TABLE IF EXISTS Oficinas;"

# Borrar tabla
cursor.execute(BorrarTabla)
print("Se ha suprimido una tabla de la base de datos")

# Finalizar transacción y cerrar
conexion.commit()
conexion.close()

Puedes consultar información de las funciones, clases y métodos de PyMySQL en la documentación de ReadTheDocs.


Ir al índice del tutorial de Python

jueves, 19 de abril de 2018

Barras de progreso, hélices y contadores




Las barras de progreso, las hélices y los contadores son elementos que se utilizan en un programa para mostrar gráficamente el avance de un proceso. Generalmente, sirven para informar a los usuarios sobre su evolución cuando duran más de unos pocos segundos. Por ello, tienen por objeto dar certidumbre a la persona que espera sobre que un proceso sigue en ejecución informando, a veces, del tiempo transcurrido y del que resta para su finalización. Es un recurso apropiado para mostrar el progreso de unos cálculos prolongados; de una transferencia de archivos; de la instalación de una aplicación, etc.

A continuación, mostraremos algunas de las posibilidades que existen para incorporar este práctico y vistoso elemento a un programa Python. Nos centraremos en los paquetes Progress y TQDM, ambos disponibles en nuestro repositorio favorito


Progress


El paquete Progress desarrollado por el griego Georgios Verigakis (Verigak) consta de varios módulos que agrupan un conjunto de clases que permiten declarar barras de progreso, hélices, contadores, etc. en programas para la consola. Son objetos de distintos tipos que tienen la misma finalidad y de los cuales existen algunas variantes.


Instalación de Progress


Para instalar Progress con PIP desde la línea de comandos:

$ pip install progress


Objetos Bar, ChargingBar, Spynner y Countdown de Progress


Normalmente los objetos se declaran antes del inicio de un bucle y, después, en cada ciclo del bucle se utiliza el método Next() para hacer que avance.

A continuación, varios ejemplos que muestran cómo declarar y usar los objetos: dos tipos de barras, una hélice y un contador. La función sleep() de time se utiliza a veces para introducir un pequeño retardo de tiempo para que se pueda observar el progreso de los distintos elementos usados.



from progress.bar import Bar, ChargingBar
import os, time, random

# Declara un objeto de la clase Bar(). En cada ciclo la barra
# muestra una porción hasta llegar a su máxima longitud en el 
# ciclo 20. La barra se representa con el carácter #

bar1 = Bar('Procesando:', max=20)
for num in range(20):
    time.sleep(0.2)
    bar1.next()
bar1.finish()


# Declara un objeto de la clase ChargingBar(). Cuando comienza
# el bucle aparece una barra punteada y durante los ciclos los 
# puntos "∙" son sustituidos por el carácter "█" hasta alcazar
# el 100%.

bar2 = ChargingBar('Instalando:', max=100)
for num in range(100):
    time.sleep(random.uniform(0, 0.2))
    bar2.next()
bar2.finish()


# Declara un objeto de la clase Bar(). En cada ciclo la barra
# muestra el carácter del atributo "fill" (·) hasta alcanzar 
# el 100%.
# Durante el proceso se escribe un archivo de texto con 
# 5000 caracteres ('X' y 'O') que son generados por una función 
# aleatoria. En este caso el retardo de tiempo es real.
# En el módulo hay otras clases para declarar objetos similares:
# FillingSquaresBar, FillingCirclesBar, IncrementalBar, PixelBar
# y ShadyBar

bar3 = Bar('Escribiendo:', fill='·', suffix='%(percent)d%%')
caracteres = ['X', 'O']
datos = os.getcwd()+os.sep+"datos.txt"
archivo = open(datos, "w")
for i in range(100):
    cadena = ""
    longitud = 5000
    for num in range(longitud):
        cadena += caracteres[random.randint(0, 1)]
    
    archivo.write(cadena + "\n")
    bar3.next()
    
bar3.finish()
archivo.close


# Declara un objeto de la clase Spinner(). En cada ciclo una hélice
# gira hasta que se completa la lectura del archivo creado en el
# ejemplo anterior. Cuando se completa la lectura se muestra el 
# número total de caracteres encontrados de cada tipo ('X'/'O').
# Una hélice muestra que un proceso se está ejecutando pero no 
# no ayuda a prever su final.
# El módulo tienes otras clase para declarar objetos similares:
# PieSpinner, MoonSpinner, LineSpinner y PixelSpinner.

from progress.spinner import Spinner
import time

spinner = Spinner('Leyendo: ')
cuenta_X = 0
cuenta_O = 0
archivo = open(datos, "r")
while True: 
    linea = archivo.readline()
    if linea:
        for caracter in linea:
            if caracter == 'X':
                cuenta_X+=1
            elif caracter == 'O':
                cuenta_O+=1
    else:
        break
    time.sleep(0.1)
    spinner.next()
    
print(' X=', cuenta_X, 'O=', cuenta_O)
archivo.close


# Declara un objeto de la clase Countdown(). En cada ciclo un 
# contador que comienza en 100 va disminuyendo su valor hasta
# alcanzar 0, que marca el fin del bucle.
# El módulo tiene otras clases para declarar objetos 
# similares: Counter, Pie y Stack

from progress.counter import Countdown
import time

contador = Countdown("Contador: ")
for num in range(100):
    contador.next()
    time.sleep(0.05)

print()


TQDM


El módulo TQDM de Noam Yorav-Raphael y un grupo de colaboradores a diferencia de progress sólo permite implementar barras de progreso, pero más sofisticadas porque son capaces de ofrecer más información mientras se ejecuta un proceso: el porcentaje ejecutado, el tiempo trascurrido, una estimación del tiempo que resta para su finalización y el número de iteraciones por segundo.

Algunas características interesantes de TQDM son que se puede utilizar en el entorno interactivo IPython, dentro de un cuaderno Jupyter y desde la línea de comandos.


Instalación de TQDM


Para instalar TQDM con PIP desde la línea de comandos:

$ pip install tqdm


Barras de progreso con TQDM


A continuación, varios ejemplos que muestran el uso de las barras de progreso TQDM:



# Declara una barra de progreso tqdm. En cada ciclo la barra
# muestra una porción hasta llegar a 100.
# La barra es representada con el carácter "█": a su izquierda
# aparece el porcentaje procesado y a su derecha el número de ciclo
# actual, el total de ciclos, el tiempo transcurrido de proceso,
# una estimación del tiempo pendiente y el número de ciclos o 
# iteraciones por segundo.

from tqdm import tqdm, trange
import time

for num in tqdm(range(100)):
    time.sleep(0.01)


# Declara una barra de progreso con trange() que es equivalente a
# tqdm(range()) del ejemplo anterior

for num in trange(100):
    time.sleep(0.01)


# Declara una barra de progreso tqdm utilizando una lista,
# correspondiéndose en este caso el número de ciclos con el 
# número de elementos de la lista.

texto = ""
for caracter in tqdm(["a", "b", "c", "d"]):
    texto = texto + caracter


# Declara una barra de progreso tqdm con una lista y
# se establece una descripción para mostrar el elemento
# en curso a la izquierda de la barra.

barra1 = tqdm(["a", "b", "c", "d"])
for caracter in barra1:
    barra1.set_description("Procesando %s" % caracter)
    time.sleep(0.5)


# Declara una barra de progreso tqdm para un bucle de
# 100 ciclos que se actualiza cada 10 ciclos.
# El carácter utilizado para construir la barra es '#'
# y lo establece el atributo ascii con el valor True.

with tqdm(total=100, ascii=True) as barra2:
    for num in range(10):
        barra2.update(10)
        time.sleep(0.5)


# Declara una barra de progreso tqdm en un bucle para
# recorrer y acumular con accumulate() los valores de una lista

from itertools import *
barra3 = tqdm(accumulate([0, 1, 2, 3, 4, 5]))
for acumulado in barra3:
    barra3.set_description("Acumulado %i" % acumulado)
    time.sleep(0.5)


# Declara una barra de progreso tqdm en un bucle para
# recorrer y acumular con accumulate() los valores de una lista.
# En ese ejemplo el atributo disable se establece con el valor
# True para no mostrar la barra de progreso

desactivado = True
barra4 = tqdm(accumulate([0, 1, 2, 3, 4, 5]), disable=desactivado)
for acumulado in barra4:
    barra4.set_description("Acumulado %i" % acumulado)
    if desactivado:
        print(acumulado, end=' ')
    time.sleep(0.5)


# Ejecutado desde la línea de comandos lista los archivos y carpetas
# del directorio /usr/ redirigiendo la salida a un archivo de texto,
# mostrando el número de elementos encontrados y el número de
# iteraciones por segundo.

$ ls /usr/ -R | tqdm >>usr.txt



Ir al índice del tutorial de Python