wake-up-neo.com

Python Datenbankverbindung schließen

Wenn ich den folgenden Code verwende, habe ich eine offene Verbindung. Wie schließe ich?

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

Verbindungen haben eine close -Methode, wie in PEP-249 (Python Database API Specification v2.0) angegeben:

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

Da die pyodbcVerbindung und Cursor beide Kontextmanager sind, wäre es heutzutage praktischer (und vorzuziehen), dies wie folgt zu schreiben:

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!! 

Siehe https://github.com/mkleehammer/pyodbc/issues/4 für eine Erklärung, warum conn.close () nicht aufgerufen wird.

Beachten Sie, dass dies im Gegensatz zum ursprünglichen Code dazu führt, dass conn.commit() aufgerufen wird. Verwenden Sie die äußere Anweisung with, um zu steuern, wann commit aufgerufen werden soll.


Beachten Sie auch, dass unabhängig davon, ob Sie die with -Anweisungen verwenden oder nicht, per the docs ,

Verbindungen werden automatisch geschlossen, wenn sie gelöscht werden (normalerweise, wenn sie den Gültigkeitsbereich verlassen), sodass Sie normalerweise nicht [conn.close()] aufrufen müssen, sondern die Verbindung explizit schließen können, wenn Sie dies wünschen.

und ähnlich für Cursor (meine Betonung):

Cursor werden automatisch geschlossen, wenn sie gelöscht werden (normalerweise, wenn sie den Gültigkeitsbereich verlassen). Daher ist der Aufruf von [csr.close()] normalerweise nicht erforderlich .

52
unutbu

Sie können die gesamte Verbindung wie folgt in einen Kontextmanager einbinden:

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()

Dann machen Sie so etwas wo immer Sie eine Datenbankverbindung brauchen:

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

Die Verbindung wird getrennt, wenn Sie den with-Block verlassen. Dadurch wird auch die Transaktion zurückgesetzt, wenn eine Ausnahme auftritt oder wenn Sie den Block nicht mit with open_db_connection("...", commit=True) geöffnet haben.

50
AndrewF

Sie können versuchen, das Pooling zu deaktivieren, das standardmäßig aktiviert ist. Siehe this Diskussion für weitere Informationen.

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

Gemäß der pyodbc-Dokumentation werden Verbindungen zum SQL-Server werden nicht standardmäßig geschlossen. Einige Datenbanktreiber schließen keine Verbindungen, wenn close () aufgerufen wird, um Roundtrips zum Server zu speichern.

Um Ihre Verbindung zu beenden, wenn Sie close () aufrufen, sollten Sie pooling auf False setzen:

import pyodbc

pyodbc.pooling = False
3
hamzed