web-dev-qa-db-fra.com

Python Connexion à la base de données Fermer

L'utilisation du code ci-dessous me laisse une connexion ouverte, comment 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
44
Merlin

Les connexions ont une méthode close comme spécifié dans PEP-249 (spécification de l'API de la base de données Python v2.0):

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

csr = conn.cursor()  
csr.close()
conn.close()     #<--- Close the connection

Étant donné que pyodbcconnexion et curseur sont tous deux des gestionnaires de contexte, de nos jours, il serait plus pratique (et préférable) d'écrire ceci comme:

import pyodbc
conn = pyodbc.connect('DRIVER=MySQL ODBC 5.1 driver;SERVER=localhost;DATABASE=spt;UID=who;PWD=testest') 
with conn:
    crs = conn.cursor()
    do_stuff
    # conn.commit() will automatically be called when Python leaves the outer `with` statement
    # Neither crs.close() nor conn.close() will be called upon leaving the the `with` statement!! 

Voir https://github.com/mkleehammer/pyodbc/issues/4 pour une explication des raisons pour lesquelles conn.close () n'est pas appelé.

Notez que contrairement au code d'origine, cela provoque l'appel de conn.commit(). Utilisez l'instruction with externe pour contrôler quand vous voulez que commit soit appelé.


Notez également que, que vous utilisiez ou non les instructions with, par the docs ,

Les connexions sont automatiquement fermées lorsqu'elles sont supprimées (généralement lorsqu'elles sortent du champ d'application), vous ne devriez donc normalement pas avoir besoin d'appeler [conn.close()], mais vous pouvez explicitement fermer la connexion si vous le souhaitez.

et de même pour les curseurs (c'est moi qui souligne):

Les curseurs sont fermés automatiquement lorsqu'ils sont supprimés (généralement lorsqu'ils sortent du champ d'application), , donc appeler [csr.close()] n'est généralement pas nécessaire .

52
unutbu

Vous pouvez envelopper toute 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 ça 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).

50
AndrewF

Vous pouvez essayer de désactiver le regroupement, qui est activé par défaut. Voir la discussion this 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
6
Matthew Rankin

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 au serveur.

Pour fermer votre connexion lorsque vous appelez close () , vous devez définir la mise en pool sur False:

import pyodbc

pyodbc.pooling = False
3
hamzed