Acceso a MySQL con Python

De WikiEducator
Saltar a: navegación, buscar


Instalar

Instalar MySQL en Linux

$ sudo apt-get install mysql-server
$ sudo apt-get install python-mysqldb
$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 30
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
 
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| mysql              | 
+--------------------+
2 rows in set (0.00 sec)
We connect to the database using the root account. We show all available databases with the SHOW DATABASES statement.
 
mysql> CREATE DATABASE testdb;
Query OK, 1 row affected (0.02 sec)
We create a new testdb database. We will use this database throughout the tutorial.
 
mysql> CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'test623';
Query OK, 0 rows affected (0.00 sec)
 
mysql> USE testdb;
Database changed
 
mysql> GRANT ALL ON testdb.* TO 'testuser'@'localhost';
Query OK, 0 rows affected (0.00 sec)
 
mysql> quit;
Bye

MySQLdb

MySQLdb es un wrapper sobre _mysql, compatible con DB API

Versión de la base de datos

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as dbapi
import sys
 
try:
    conn = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
    cursor = conn.cursor()
 
    cursor.execute("SELECT VERSION()")
    data = cursor.fetchone()
 
    cursor.close()
    conn.close()
 
except dbapi.Error, e:
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)
 
print "Database version : %s " % data


Creación de tablas e inserción de datos

import MySQLdb as dbapi
import sys
 
try:
    con = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
 
    cursor = con.cursor()
    cursor.execute("CREATE TABLE IF NOT EXISTS \
        Escritores(Id INT PRIMARY KEY AUTO_INCREMENT, Nombre VARCHAR(25))")
    cursor.execute("INSERT INTO Escritores(Nombre) VALUES('Jack London')")
    cursor.execute("INSERT INTO Escritores(Nombre) VALUES('Honore de Balzac')")
    cursor.execute("INSERT INTO Escritores(Nombre) VALUES('Lion Feuchtwanger')")
    cursor.execute("INSERT INTO Escritores(Nombre) VALUES('Emile Zola')")
    cursor.execute("INSERT INTO Escritores(Nombre) VALUES('Truman Capote')")
 
    con.commit()
 
    cursor.close()
    con.close()
 
except dbapi.Error, e:
 
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)


mysql> SELECT * FROM Escritores;
+----+-------------------+
| Id | Nombre            |
+----+-------------------+
|  1 | Jack London       |
|  2 | Honore de Balzac  |
|  3 | Lion Feuchtwanger |
|  4 | Emile Zola        |
|  5 | Truman Capote     |
+----+-------------------+
5 rows in set (0.00 sec)

Recuperar datos

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as dbapi
import sys
 
try:
    con = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
 
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM Escritores")
 
    rows = cursor.fetchall()
 
    for row in rows:
        print row
 
    cursor.close()
    conn.close()
 
except dbapi.Error, e:
 
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)
$ ./recupera.py
(1L, 'Jack London')
(2L, 'Honore de Balzac')
(3L, 'Lion Feuchtwanger')
(4L, 'Emile Zola')
(5L, 'Truman Capote')

Recupera uno a uno

    con = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
 
    cursor = con.cursor()
    cursor.execute("SELECT * FROM Escritores")
 
    numrows = int(cursor.rowcount)
 
    for i in range(numrows):
        row = cursor.fetchone()
        print row[0], row[1]
 
    cursor.close()
    conn.close()

Cursor Diccionario (DictCursor)

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as dbapi
import sys
 
try:
    conn = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
 
    cursor = conn.cursor(dbapi.cursors.DictCursor)
    cursor.execute("SELECT * FROM Escritores")
 
    rows = cursor.fetchall()
 
    for row in rows:
        print "%s %s" % (row["Id"], row["Name"])
 
    cursor.close()
    conn.close()
 
except dbapi.Error, e:
 
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)


Usando descripción del cursor

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as dbapi
import sys
 
try:
    conn = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
 
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM Escritores")
 
    rows = cursor.fetchall()
 
    desc = cursor.description
 
    print "%s %3s" % (desc[0][0], desc[1][0])
 
    for row in rows:    
        print "%2s %3s" % row
 
    cursor.close()
    conn.close()
 
except dbapi.Error, e:
 
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)


Sentencias preparadas

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as dbapi
import sys
 
try:
    conn = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
 
    cursor = conn.cursor()
 
    cursor.execute("UPDATE Escritores SET Name = %s WHERE Id = %s", 
        ("Guy de Maupasant", "4"))        
 
    print "Number of rows updated: %d" % cursor.rowcount
 
    cursor.close()
    conn.close()
 
except dbapi.Error, e:
 
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)
mysql> SELECT Name FROM Escritores WHERE Id=4;
+------------------+
| Name             |
+------------------+
| Guy de Maupasant |
+------------------+
1 row in set (0.00 sec)

Escritura de imágenes

Las imágenes son datos binarios. MySQL tiene un tipo de dato especial: BLOB (Binary Large Object).

mysql> CREATE TABLE Imagenes(Id INT PRIMARY KEY AUTO_INCREMENT, Data MEDIUMBLOB);
Query OK, 0 rows affected (0.06 sec)
#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as dbapi
import sys
 
try:
    fin = open("foto.png")
    img = fin.read()
    fin.close()
 
except IOError, e:
 
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)
 
 
try:
    conn = dbapi.connect(host='localhost',user='testuser', passwd='test623', db='testdb')
    cursor = conn.cursor()
    cursor.execute("INSERT INTO Imagenes SET Data='%s'" % \
        dbapi.escape_string(img))
 
    conn.commit()
 
    cursor.close()
    conn.close()
 
except dbapi.Error, e:
 
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)
In the above script, we read a png image and insert it into the Images table.
 
fin = open("chrome.png")
img = fin.read()
We open and read an image. The read() function returns the data as string.
 
cursor.execute("INSERT INTO Images SET Data='%s'" % dbapi.escape_string(img))

Leer imágenes

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as dbapi
import sys
 
try:
    conn = dbapi.connect(host='localhost',user='testuser', passwd='test623', db='testdb')
 
    cursor = conn.cursor()
 
    cursor.execute("SELECT Data FROM Imagenes LIMIT 1")
 
    fout = open('image.png','wb')
    fout.write(cursor.fetchone()[0])
    fout.close()
 
    cursor.close()
    conn.close()
 
except IOError, e:
 
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)

Transacciones

Una transacción es una operación "atómica" en la base de datos.

MySQL tiene dos motores: MyISAM y InnoDB. MyISAM (por defecto) es muy rápido, pero no soporta transacciones.

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as mdb
import sys
 
try:
    conn = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
 
    cursor = conn.cursor()
 
    cursor.execute("UPDATE Escritores SET Name = %s WHERE Id = %s", 
        ("Leo Tolstoy", "1"))       
    cursor.execute("UPDATE Escritores SET Name = %s WHERE Id = %s", 
        ("Boris Pasternak", "2"))
    cursor.execute("UPDATE Writer SET Name = %s WHERE Id = %s", 
        ("Leonid Leonov", "3"))   
 
    conn.commit()
 
    cursor.close()
    conn.close()
 
except dbapi.Error, e:
 
    conn.rollback()
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)
$ ./test_transaccion.py
Error 1146: Table 'testdb.Writer' doesn't exist
 
mysql> SELECT * FROM Escritores;
+----+-------------------+
| Id | Name              |
+----+-------------------+
|  1 | Leo Tolstoy       |
|  2 | Boris Pasternak   |
|  3 | Lion Feuchtwanger |
|  4 | Guy de Maupasant  |
|  5 | Truman Capote     |
+----+-------------------+
5 rows in set (0.00 sec)

Hay un error, pero las primeras filas se han cambiado.

DROP TABLE Escritores;
 
CREATE TABLE IF NOT EXISTS Escritores(Id INT PRIMARY KEY AUTO_INCREMENT, 
    Name VARCHAR(25)) ENGINE=INNODB;
 
INSERT INTO Escritores(Nombre) VALUES('Jack London');
INSERT INTO Escritores(Nombre) VALUES('Honore de Balzac');
INSERT INTO Escritores(Nombre) VALUES('Lion Feuchtwanger');
INSERT INTO Escritores(Nombre) VALUES('Emile Zola');
INSERT INTO Escritores(Nombre) VALUES('Truman Capote');
#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import MySQLdb as dbapi
import sys
 
try:
    conn = dbapi.connect('localhost', 'testuser', 'test623', 'testdb');
 
    cursor = conn.cursor()
 
    cursor.execute("DELETE FROM Escritores WHERE Id = 5")  
    cursor.execute("DELETE FROM Escritores WHERE Id = 4") 
    cursor.execute("DELETE FROM Writer WHERE Id = 3") 
 
    conn.commmit()
 
except dbapi.Error, e:
 
    conn.rollback()
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)
 
cursor.close()
conn.close()
$ ./innodb.py
Error 1146: Table 'testdb.Writer' doesn't exist
 
mysql> SELECT * FROM Escritores;
+----+-------------------+
| Id | Name              |
+----+-------------------+
|  1 | Jack London       |
|  2 | Honore de Balzac  |
|  3 | Lion Feuchtwanger |
|  4 | Emile Zola        |
|  5 | Truman Capote     |
+----+-------------------+
5 rows in set (0.00 sec)

El error se produce antes del commit y entra en juego el método rollback.