devstory

Connectez-vous à la base de données MySQL en Python en utilisant PyMySQL

  1. Qu'est-ce que c'est PyMySQL?
  2. Installation PyMySQL
  3. Exemple de la base de données
  4. Connectez- vous MySQL à partir de Python avec PyMySQL
  5. Exemple de la requête
  6. Exemple Insert
  7. Exemple Update
  8. Exemple Delete
  9. Appel la procédure
  10. Appel la fonction

1. Qu'est-ce que c'est PyMySQL?

Afin de connecter Python avec une base de données d'un Driver (le conducteur), il est une bibliothèque qui serve à interagir avec la base de données. Avec la base de données MySQL vous avez 3 choix de tel Driver:
  • MySQL/connector for Python
  • MySQLdb
  • PyMySQL
Driver
Description
MySQL/Connector pour Python
C'est une bibliothèque fournie par la communauté MySQL.
MySQLdb
MySQLdb est la bibliothèque qui connecte à MySQL từà partir de Python, elle est écrite en langage C, elle est gratuite et est le logiciel à source ouverte.
PyMySQL
C'est une bibliothèque qui connecte à MySQL à partir de Python, est une pure bibliothèque Python. L'objectif de PyMySQL est de remplacer MySQLdb et de travailler en CPython, PyPy et IronPython.
PyMySQL est un projet de code source ouvert , et vous pouvez voir son code source ici:

2. Installation PyMySQL

Pour installer PyMySQL sur Windows (Ou Ubuntu/Linux) vous devez ouvrir la fenêtre CMD, et exécutez l'instruction ci- dessous:
pip install PyMySQL

3. Exemple de la base de données

"simplehr" est un exemple de la base de données utilisé dans de nombreux tutoriels sur o7planning. Dans ce document, je vais l'utiliser aussi. Vous pouvez créer la base de données basée sur l'instruction ci- dessous:

4. Connectez- vous MySQL à partir de Python avec PyMySQL

Le simple exemple ci- dessous utilise Python pour connecter à MySQL et requêter la table Department:
connectExample.py
import pymysql.cursors   
# Connectez- vous à la base de données.
connection = pymysql.connect(host='192.168.5.134',
                             user='root',
                             password='1234',                             
                             db='simplehr',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor) 
print ("connect successful!!") 
try:  
    with connection.cursor() as cursor: 
        # SQL 
        sql = "SELECT Dept_No, Dept_Name FROM Department " 
        # Exécutez la requête (Execute Query).
        cursor.execute(sql) 
        print ("cursor.description: ", cursor.description) 
        print() 
        for row in cursor:
            print(row) 
finally:
    # Closez la connexion (Close connection).      
    connection.close()
Les résultats de l'exemple:
connect successful!!
cursor.description: (('Dept_No', 253, None, 80, 80, 0, False), ('Dept_Name', 253, None, 1020, 1020, 0, False))

{'Dept_No': 'D10', 'Dept_Name': 'ACCOUNTING'}
{'Dept_No': 'D20', 'Dept_Name': 'RESEARCH'}
{'Dept_No': 'D30', 'Dept_Name': 'SALES'}
{'Dept_No': 'D40', 'Dept_Name': 'OPERATIONS'}
Le module utilitaire:
Le conseil ici est que vous devriez créer un module utilitaire pour connecter à la base de données. Ici, je crée un module baptisé "myconnutils", ce module définie la fonction getConnection() pour renvoyer une connection.
myconnutils.py
import pymysql.cursors   
# La fonction renvoie une connexion.
def getConnection(): 
    # Vous pouvez changer les arguments de la connexion.
    connection = pymysql.connect(host='192.168.5.129',
                                 user='root',
                                 password='1234',                             
                                 db='simplehr',
                                 charset='utf8mb4',
                                 cursorclass=pymysql.cursors.DictCursor)
    return connection

5. Exemple de la requête

L'exemple ci- dessous requête la table Employee, Pythonutilise%s comme un "bouche- trou" (placeholder) pour le paramètre, qui ne est indépendant du type de paramètre. Par exemple:
sql1 = "Insert into Department (Dept_Id, Dept_No, Dept_Name) values (%s, %s, %s) "

sql2 = "Select * from Employee Where Dept_Id = %s "
queryExample.py
# Utilisez votre module utilitaire.
import myconnutils 

connection = myconnutils.getConnection() 
print ("Connect successful!") 
sql = "Select Emp_No, Emp_Name, Hire_Date from Employee Where Dept_Id = %s " 
try :
    cursor = connection.cursor() 
    # Exécutez sql et passez- lui un paramètre.
    cursor.execute(sql, ( 10 ) )  
    print ("cursor.description: ", cursor.description) 
    print() 
    for row in cursor:
        print (" ----------- ")
        print("Row: ", row)
        print ("Emp_No: ", row["Emp_No"])
        print ("Emp_Name: ", row["Emp_Name"])
        print ("Hire_Date: ", row["Hire_Date"] , type(row["Hire_Date"]) ) 
finally:
    # Achevez la connexion
    connection.close()

6. Exemple Insert

insertExample.py
# Utilisez votre module utilitaire.
import myconnutils
import pymysql.cursors  

connection = myconnutils.getConnection() 
print ("Connect successful!")  
try :
    cursor = connection.cursor() 
    sql = "Select max(Grade) as Max_Grade from Salary_Grade "
    cursor.execute(sql) 
    # Une ligne de données
    oneRow = cursor.fetchone()      

    # Output: {'Max_Grade': 4} or {'Max_Grade': None}
    print ("Row Result: ", oneRow) 
    grade = 1
    
    if oneRow != None and oneRow["Max_Grade"] != None:
        grade = oneRow["Max_Grade"] + 1 
    cursor = connection.cursor()  
    sql =  "Insert into Salary_Grade (Grade, High_Salary, Low_Salary) " \
         + " values (%s, %s, %s) " 
    print ("Insert Grade: ", grade)  
    # Exécutez sql et attribuez-lui 3 paramètres
    cursor.execute(sql, (grade, 2000, 1000 ) ) 
    connection.commit()  
finally: 
    connection.close()
Output:
connect successful!!
Row Result: {'Max_Grade': 2}
Insert Grade: 3

7. Exemple Update

updateExample.py
# Utilisez votre module utilitaire
import myconnutils
import pymysql.cursors 
import datetime 

connection = myconnutils.getConnection() 
print ("Connect successful!")  
try :
    cursor = connection.cursor() 
    sql = "Update Employee set Salary = %s, Hire_Date = %s where Emp_Id = %s "   
    # Hire_Date
    newHireDate = datetime.date(2002, 10, 11) 
    # Exécutez sql et passez 3 paramètres.
    rowCount = cursor.execute(sql, (850, newHireDate, 7369 ) ) 
    connection.commit()  
    print ("Updated! ", rowCount, " rows") 
finally:
    # Achevez la connexion    
    connection.close()
Output:
connect successful!
Update! 1 rows

8. Exemple Delete

deleteExample.py
# Utilisez votre module utilitaire.
import myconnutils 

connection = myconnutils.getConnection() 
print ("Connect successful!")  
try :
    cursor = connection.cursor() 
    sql = "Delete from Salary_Grade where Grade = %s"  
    
    # Exécutez sql et passez un paramètre
    rowCount = cursor.execute(sql, ( 3 ) ) 
    connection.commit()  
    print ("Deleted! ", rowCount, " rows") 
finally:
    # Achevez la connexion
    connection.close()
Output:
connect successful!
Deleted! 1 rows

9. Appel la procédure

Il y a des problèmes lorsque vous appelez une fonction (function) ou une procédure (procedure) dans Python. J'ai mis en place une situation comme celle-ci:
You have a procedure:
  • Get_Employee_Info(p_Emp_Id, v_Emp_No, v_First_Name, v_Last_Name, v_Hire_Date)
get_Employee_Info
DELIMITER $$

-- This procedure retrieves information of an employee,
-- Input parameter: p_Emp_ID (Integer)
-- There are four output parameters v_Emp_No, v_First_Name, v_Last_Name, v_Hire_Date

CREATE PROCEDURE get_Employee_Info(p_Emp_ID     Integer,
                                 out       v_Emp_No        Varchar(50) ,
                                 out       v_First_Name    Varchar(50) ,
                                 Out       v_Last_name    Varchar(50) ,
                                 Out       v_Hire_date      Date)
BEGIN
set v_Emp_No  = concat( 'E' , Cast(p_Emp_Id as char(15)) );
--
set v_First_Name = 'Michael';
set v_Last_Name  = 'Smith';
set v_Hire_date  = curdate();
END
La procédure ci- dessus a un paramètre d'entrée p_Emp_Id et 4 paramètre de sortie v_Emp_No, v_First_Name, v_Last_Name, v_Hire_Date, vous appelez cette procédure à partir de Python et mettre la valeur p_Emp_Id dedans pour prendre valeurs de sortir. C'est regretable parce que les valeurs recevues ne respondent pas de la demande comme prévu (Cela va être éclairé particulièrement dans DB-API). Python ne peut que prendre les valeurs de la proposition SELECT.
DB-API specification:
def callproc(self, procname, args=()):
    """Execute stored procedure procname with args

    procname -- string, name of procedure to execute on server

    args -- Sequence of parameters to use with procedure

    Returns the original args.

    Compatibility warning: PEP-249 specifies that any modified
    parameters must be returned. This is currently impossible
    as they are only available by storing them in a server
    variable and then retrieved by a query. Since stored
    procedures return zero or more result sets, there is no
    reliable way to get at OUT or INOUT parameters via callproc.
    The server variables are named @_procname_n, where procname
    is the parameter above and n is the position of the parameter
    (from zero). Once all result sets generated by the procedure
    have been fetched, you can issue a SELECT @_procname_0, ...
    query using .execute() to get any OUT or INOUT values.

    Compatibility warning: The act of calling a stored procedure
    itself creates an empty result set. This appears after any
    result sets generated by the procedure. This is non-standard
    behavior with respect to the DB-API. Be sure to use nextset()
    to advance through all result sets; otherwise you may get
    disconnected.
    """
Mais vous pouvez complètement résoudre ce problème ci- dessus, vous devez emballer (wrap) la procédure ci- dessus Get_Employee_Info par une autre procédure (Par exemple Get_Employee_Info_Wrap), cette procédure renvoie des valeurs à travers la proposion SELECT (Select clause).
get_Employee_Info_Wrap
DROP procedure IF EXISTS `get_Employee_Info_Wrap`;

DELIMITER $$

-- This procedure wrap Get_Employee_info
CREATE PROCEDURE get_Employee_Info_Wrap(p_Emp_ID     Integer,
                                   out       v_Emp_No        Varchar(50) ,
                                   out       v_First_Name    Varchar(50) ,
                                   Out       v_Last_name    Varchar(50) ,
                                   Out       v_Hire_date      Date)
BEGIN
Call get_Employee_Info( p_Emp_Id, v_Emp_No, v_First_Name, v_Last_Name, v_Hire_Date); 
-- SELECT
Select v_Emp_No, v_First_Name, v_Last_Name, v_Hire_Date;  
END
Au lieu d'appeler la procédure Get_Employee_Info en Python, appelez la procédure Get_Employee_Info_Wrap.
callProcedureExample.py
# Utilisez votre module utilitaire
import myconnutils 
import datetime 

connection = myconnutils.getConnection() 
print ("Connect successful!")  
try :
    cursor = connection.cursor() 
    # Get_Employee_Info_Wrap               
    # @p_Emp_Id       Integer ,
    # @v_Emp_No       Varchar(50)   OUTPUT
    # @v_First_Name   Varchar(50)   OUTPUT
    # @v_Last_Name    Varchar(50)   OUTPUT
    # @v_Hire_Date    Date          OUTPUT   
    v_Emp_No = ""
    v_First_Name= ""
    v_Last_Name= ""
    v_Hire_Date = None
    
    inOutParams = ( 100, v_Emp_No, v_First_Name , v_Last_Name, v_Hire_Date ) 
    resultArgs = cursor.callproc("Get_Employee_Info_Wrap" , inOutParams   )  
    
    print ('resultArgs:', resultArgs )
    print ( 'inOutParams:', inOutParams ) 
    print (' ----------------------------------- ') 
    for row in cursor:
        print('Row: ',  row )
        print('Row[v_Emp_No]: ',  row['v_Emp_No'] )
        print('Row[v_First_Name]: ',  row['v_First_Name'] )
        print('Row[v_Last_Name]: ',  row['v_Last_Name'] ) 
        # datetime.date
        v_Hire_Date =  row['v_Hire_Date'] 
        print('Row[v_Hire_Date]: ', v_Hire_Date )  
finally:
    # Achevez la connexion
    connection.close()
Exécutez l'exemple:
connect successful!
resultArgs: (100, '', '', '', None)
inOutParams: (100, '', '', '', None)
 -----------------------------------
Row: {'v_Emp_No': 'E100', 'v_First_Name': 'Michael', 'v_Last_Name': 'Smith', 'v_Hire_Date': datetime.date(2017, 5, 17)}
Row[v_Emp_No]: E100
Row[v_First_Name]: Michael
Row[v_Last_Name]: Smith
Row[v_Hire_Date]: 2017-05-17

10. Appel la fonction

Afin d'appeler une fonction (function) en Python, vous devez créer une cause de requête (query clause), et exécuter cette cause de requête.
Ci-dessous est la focntion Get_Emp_No, le paramètre d'entrée est p_Emp_Id et renvoie Emp_No (Le code de l'employé).
Get_Emp_No
DROP function  if Exists `Get_Emp_No`;
 
DELIMITER $$

CREATE Function Get_Emp_No (p_Emp_Id  Integer) Returns Varchar(50)
Begin    

   return  concat('E', CAST(p_Emp_Id  as  char)) ;
  
END;
callFunctionExample.py
# Utilisez votre module utilitaire
import myconnutils 
import datetime 

connection = myconnutils.getConnection() 
print ("Connect successful!")  
try :
    cursor = connection.cursor() 
    # Get_Employee_Info_Wrap               
    # @p_Emp_Id       Integer  
    v_Emp_No = ""  
    inOutParams = ( 100 ) 
    sql = "Select Get_Emp_No(%s) as Emp_No " 
    cursor.execute(sql, ( 100 ) )  
    print (' ----------------------------------- ') 
    for row in cursor:
        print('Row: ',  row )
        print('Row[Emp_No]: ',  row['Emp_No'] )  
finally:
    # Closez la connexion (Close connection).    
    connection.close()
Exécutez l'exemple:
connect successful!
 -----------------------------------  
Row: {'Emp_No': 'E100'}
Row[Emp_No]: E100