it-swarm.com.de

Was ist, wenn ich die Datenbankverbindung in Python SQLite nicht schließe?

Ich mache so etwas ...

conn = sqlite3.connect(db_filename)

with conn:
    cur = conn.cursor()
    cur.execute( ... )

with übernimmt die Änderungen automatisch. Die Dokumente sagen jedoch nichts über das Schließen der Verbindung aus. 

Tatsächlich kann ich conn in späteren Anweisungen (die ich getestet habe) verwenden. Daher scheint es, dass der Kontextmanager die Verbindung NICHT schließt.

Muss ich die Verbindung manuell trennen? Was ist, wenn ich es offen lasse?

EDIT

Meine Schlussfolgerungen ...

  • Die Verbindung ist NICHT geschlossen im Kontextmanager habe ich getestet und bestätigt. Bei __exit__ übernimmt der Kontextmanager NUR die Änderungen durch Ausführen von conn.commit().
  • with conn und with sqlite3.connect(db_filename) as conn sind ein und dasselbe . Wenn Sie also eine der beiden Optionen verwenden, bleibt die Verbindung erhalten
  • Die with-Anweisung erstellt KEINEN neuen Gültigkeitsbereich. Daher sind alle innerhalb der Suite von mit erstellten Variablen auch außerhalb zugänglich
  • Zum Schluss sollten Sie die Verbindung manuell schließen
50
treecoder

Die Antwort auf die spezifische Frage, was passiert, wenn Sie keine SQLite-Datenbank schließen, ist ziemlich einfach und gilt für die Verwendung von SQLite in einer beliebigen Programmiersprache. Wenn die Verbindung explizit durch Code oder implizit durch Programmende geschlossen wird, wird jede ausstehende Transaktion zurückgesetzt. (Das Rollback wird tatsächlich vom nächsten Programm zum Öffnen der Datenbank ausgeführt.) Wenn keine ausstehende Transaktion geöffnet ist, passiert nichts.

Dies bedeutet, dass Sie sich nicht zu viele Gedanken darüber machen müssen, dass die Datenbank vor dem Beenden des Prozesses immer geschlossen wird, und dass Sie auf Transaktionen achten sollten, die sicherstellen, dass Sie sie starten und an geeigneten Stellen festlegen.

31
Roger Binns

Sie haben hier ein gültiges Grundproblem, es ist jedoch auch wichtig zu verstehen, wie sqlite funktioniert:

1. connection open
    2. transaction started
        3. statement executes
    4. transaction done
5. connection closed

in Bezug auf Datengenauigkeit müssen Sie sich nur um Transaktionen kümmern und nicht um offene Handles. sqlite hält nur eine Sperre für eine Datenbank innerhalb einer Transaktion (*) oder einer Anweisungsausführung.

in Bezug auf Ressourcenmanagement , z. Wenn Sie vorhaben, die sqlite-Datei zu entfernen oder so viele Verbindungen zu verwenden, dass Ihnen möglicherweise die Dateideskriptoren ausgehen, achten Sie auch auf offene Out-of-Transaction-Verbindungen.

es gibt zwei Möglichkeiten, eine Verbindung zu schließen: Entweder rufen Sie .close() explizit auf. Danach haben Sie noch ein Handle, können es aber nicht verwenden, oder Sie lassen die Verbindung außerhalb des Gültigkeitsbereichs und sammeln die gesammelten Abfälle.

wenn Sie eine Verbindung schließen müssen , schließen Sie sie explizit gemäß dem Motto von Python " explizit ist besser als implizit ."

wenn Sie nur den Code auf Nebeneffekte prüfen, kann es akzeptabel sein, die letzte Variable, die den Verweis auf die Verbindung enthält, außerhalb des Gültigkeitsbereichs zu lassen. Beachten Sie jedoch, dass Ausnahmen den Stack und damit den Verweis in diesem Stack erfassen. Wenn Sie Ausnahmen übergeben, kann die Lebensdauer der Verbindung beliebig verlängert werden.

caveat programmator , sqlite verwendet standardmäßig "verzögerte" Transaktionen, dh die Transaktion wird nur gestartet, wenn Sie eine Anweisung ausführen. Im obigen Beispiel wird die Transaktion von 3 bis 4 und nicht von 2 bis 4 ausgeführt.

7
Dima Tisnek

Dies ist der Code, den ich verwende. Die Connection und die Cursor werden dank contextlib.closing() automatisch geschlossen. Die Connection wird dank des Kontextmanagers automatisch festgeschrieben.

import sqlite3
import contextlib

def execute_statement(statement):
    with contextlib.closing(sqlite3.connect(path_to_file)) as conn: # auto-closes
        with conn: # auto-commits
            with contextlib.closing(conn.cursor()) as cursor: # auto-closes
                cursor.execute(statement)

Sie können einen with-Block wie folgt verwenden:

from contextlib import closing
import sqlite3

def query(self, db_name, sql):
    with closing(sqlite3.connect(db_name)) as con, con,  \
            closing(con.cursor()) as cur:
        cur.execute(sql)
        return cur.fetchall()
  • verbindet
  • startet eine Transaktion
  • erzeugt einen DB-Cursor
  • formt die Operation vor und gibt die Ergebnisse zurück
  • schließt den Cursor
  • bestätigt die Transaktion
  • schließt die Verbindung

alles sicher in glücklichen und außergewöhnlichen Fällen

3

Ihre Version lässt conn nach der Verwendung der Verbindung in den Gültigkeitsbereich.

BEISPIEL:

Deine Version

    conn = sqlite3.connect(db_filename) #DECLARE CONNECTION OUT OF WITH BLOCK

    with conn:                          #USE CONNECTION IN WITH BLOCK
        cur = conn.cursor()
        cur.execute( ... )

   #conn variable is still in scope, so you can use it again

neue Version  

    with sqlite3.connect(db_filename) as conn:  #DECLARE CONNECTION AT START OF WITH BLOCK
        cur = conn.cursor()
        cur.execute( ... )   

   #conn variable is out of scope, so connection is closed 
   # MIGHT BE IT IS NOT CLOSED BUT WHAT  Avaris SAID!
   #(I believe auto close goes for with block)
1
elrado

Um eine Verbindung zu einer Datenbank zu verwalten, mache ich das normalerweise. 

# query method belonging to a DB manager class

def query (self, sql):
    con = sqlite3.connect(self.dbName)
    with con:
        cur = con.cursor()
        cur.execute(sql)
        res = cur.fetchall()
    if con:
        con.close()

    return res

ich bin mir sicher, dass die Verbindung explizit geschlossen wird.

0
Guido