Mysql
 sql >> Database >  >> RDS >> Mysql

Corretta gestione delle risorse del database:cursore e connessione

Sembra un ottimo caso d'uso per un gestore di contesto python . I Context Manager ti consentono di gestire correttamente le risorse , come una connessione al database, consentendoti di specificare come dovrebbero funzionare i metodi di configurazione e smantellamento della tua risorsa . Puoi creare il tuo gestore di contesto personalizzato in uno dei due modi:in primo luogo, avvolgendo la tua classe di database e implementando i metodi richiesti per il gestore di contesto:__init__() , __enter__() e __exit__() . In secondo luogo, utilizzando un @contextmanager decoratore su una definizione di funzione e creando un generatore per la risorsa del database all'interno di detta definizione di funzione. Mostrerò entrambi gli approcci e ti lascerò decidere quale è la tua preferenza. Il __init__() è il metodo di inizializzazione per il tuo gestore di contesto personalizzato, simile al metodo di inizializzazione utilizzato per le classi python personalizzate. Il __enter__() metodo è il tuo codice di configurazione per il tuo gestore di contesto personalizzato. Infine, il __exit()__ metodo è il tuo smontaggio codice per il tuo gestore di contesto personalizzato. Entrambi gli approcci utilizzano questi metodi con la differenza principale che il primo metodo indicherà esplicitamente questi metodi all'interno della definizione della tua classe. Dove, come nel secondo approccio, tutto il codice fino al yield del tuo generatore istruzione è il tuo codice di inizializzazione e configurazione e tutto il codice dopo il yield statement è il tuo codice di smontaggio. Considererei anche l'estrazione delle azioni del database basate sull'utente in una classe modello utente. Qualcosa sulla falsariga di:

gestore del contesto personalizzato:(approccio basato sulla classe ):

import pymysql

class MyDatabase():
    def __init__(self):
        self.host = '127.0.0.1'
        self.user = 'root'
        self.password = ''
        self.db = 'API'

        self.con = None
        self.cur = None

    def __enter__(self):
        # connect to database
        self.con = pymysql.connect(host=self.host, user=self.user, password=self.password, db=self.db, cursorclass=pymysql.cursors.DictCursor, autocommit=True)
        self.cur = self.con.cursor()
        return self.cur

    def __exit__(self, exc_type, exc_val, traceback):
        # params after self are for dealing with exceptions
        self.con.close()

user.py (refactored) :'

# import your custom context manager created from the step above
# if you called your custom context manager file my_database.py: from my_database import MyDatabase

import <custom_context_manager>

class User:
    def getUser(self, id):
        sql = 'SELECT * from users where id = %d'
        with MyDatabase() as db: 
            db.execute(sql, (id))
            result = db.fetchall()

        return result

    def getAllUsers(self):
        sql = 'SELECT * from users'
        with MyDatabase() as db: 
            db.execute(sql)
            result = db.fetchall()
        return result

    def AddUser(self, firstName, lastName, email):
        sql = "INSERT INTO `users` (`firstName`, `lastName`, `email`) VALUES (%s, %s, %s)"
        with MyDatabase() as db:
            db.execute(sql, (firstName, lastName, email))

gestore del contesto (approccio decoratore) :

from contextlib import contextmanager
import pymysql


@contextmanager
def my_database():
    try:
        host = '127.0.0.1'
        user = 'root'
        password = ''
        db = 'API'
        con = pymysql.connect(host=host, user=user, password=password, db=db, cursorclass=pymysql.cursors.DictCursor, autocommit=True)
        cur = con.cursor()
        yield cur
    finally:
        con.close()

Quindi all'interno del tuo User class puoi usare il gestore del contesto importando prima il file e poi usandolo in modo simile a prima:

with my_database() as db:
   sql = <whatever sql stmt you wish to execute>
   #db action 
   db.execute(sql)

Spero che questo aiuti!