94 votes

Connexion à la base de données Python Fermer

L'utilisation du code ci-dessous me laisse une connexion ouverte, comment puis-je fermer ?

 import pyodbc
conn = pyodbc.connect('DRIVER=MySQL ODBC 5.1 driver;SERVER=localhost;DATABASE=spt;UID=who;PWD=testest') 

csr = conn.cursor()  
csr.close()
del csr

63voto

AndrewF Points 2301

Vous pouvez envelopper l'ensemble de la connexion dans un gestionnaire de contexte, comme suit :

 from contextlib import contextmanager
import pyodbc
import sys

@contextmanager
def open_db_connection(connection_string, commit=False):
    connection = pyodbc.connect(connection_string)
    cursor = connection.cursor()
    try:
        yield cursor
    except pyodbc.DatabaseError as err:
        error, = err.args
        sys.stderr.write(error.message)
        cursor.execute("ROLLBACK")
        raise err
    else:
        if commit:
            cursor.execute("COMMIT")
        else:
            cursor.execute("ROLLBACK")
    finally:
        connection.close()

Ensuite, faites quelque chose comme ceci partout où vous avez besoin d'une connexion à une base de données :

 with open_db_connection("...") as cursor:
    # Your code here

La connexion se fermera lorsque vous quitterez le bloc with. Cela annulera également la transaction si une exception se produit ou si vous n'avez pas ouvert le bloc à l'aide de with open_db_connection("...", commit=True) .

8voto

Matthew Rankin Points 71628

Vous pouvez essayer de désactiver le pool, qui est activé par défaut. Voir cette discussion pour plus d'informations.

 import pyodbc
pyodbc.pooling = False
conn = pyodbc.connect('DRIVER=MySQL ODBC 5.1 driver;SERVER=localhost;DATABASE=spt;UID=who;PWD=testest') 

csr = conn.cursor()  
csr.close()
del csr

6voto

Betran Jacob Points 170

Vous pouvez définir une classe DB comme ci-dessous. De plus, comme l' a suggéré Andrewf, utilisez un gestionnaire de contexte pour l'accès au curseur. Je le définirais comme une fonction membre. De cette façon, il maintient la connexion ouverte sur plusieurs transactions à partir du code de l'application et évite les reconnexions inutiles au serveur.

 import pyodbc

class MS_DB():
    """ Collection of helper methods to query the MS SQL Server database.
    """

    def __init__(self, username, password, host, port=1433, initial_db='dev_db'):
        self.username = username
        self._password = password
        self.host = host
        self.port = str(port)
        self.db = initial_db
        conn_str = 'DRIVER=DRIVER=ODBC Driver 13 for SQL Server;SERVER='+ \
                    self.host + ';PORT='+ self.port +';DATABASE='+ \
                    self.db +';UID='+ self.username +';PWD='+ \ 
                    self._password +';'
        print('Connected to DB:', conn_str)
        self._connection = pyodbc.connect(conn_str)        
        pyodbc.pooling = False

    def __repr__(self):
        return f"MS-SQLServer('{self.username}', <password hidden>, '{self.host}', '{self.port}', '{self.db}')"

    def __str__(self):
        return f"MS-SQLServer Module for STP on {self.host}"

    def __del__(self):
        self._connection.close()
        print("Connection closed.")

    @contextmanager
    def cursor(self, commit: bool = False):
        """
        A context manager style of using a DB cursor for database operations. 
        This function should be used for any database queries or operations that 
        need to be done. 

        :param commit:
        A boolean value that says whether to commit any database changes to the database. Defaults to False.
        :type commit: bool
        """
        cursor = self._connection.cursor()
        try:
            yield cursor
        except pyodbc.DatabaseError as err:
            print("DatabaseError {} ".format(err))
            cursor.rollback()
            raise err
        else:
            if commit:
                cursor.commit()
        finally:
            cursor.close()

ms_db = MS_DB(username='my_user', password='my_secret', host='hostname')
with ms_db.cursor() as cursor:
        cursor.execute("SELECT @@version;")
        print(cur.fetchall())

4voto

hamzed Points 61

Selon la documentation de pyodbc, les connexions au serveur SQL ne sont pas fermées par défaut. Certains pilotes de base de données ne ferment pas les connexions lorsque close() est appelé afin d'économiser les allers-retours vers le serveur.

Pour fermer votre connexion lorsque vous appelez close(), vous devez définir pooling sur False :

 import pyodbc

pyodbc.pooling = False

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X