105 votes

Que se passe-t-il si je ne ferme pas la connexion à la base de données en Python SQLite ?

Je suis en train de faire quelque chose comme ça...

conn = sqlite3.connect(db_filename)

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

with valide automatiquement les modifications. Mais la documentation ne dit rien sur la fermeture de la connexion.

En fait, je peux utiliser conn dans les déclarations ultérieures (que j'ai testées). Il semble donc que le gestionnaire de contexte ne ferme pas la connexion.

Dois-je fermer manuellement la connexion ? Que se passe-t-il si je la laisse ouverte ?

EDIT

Mes conclusions :

  • En la connexion n'est pas fermée dans le gestionnaire de contexte, je l'ai testé et confirmé. Lors de __exit__ le gestionnaire de contexte ne valide les modifications qu'en faisant conn.commit()
  • with conn y with sqlite3.connect(db_filename) as conn sont les mêmes, de sorte que l'utilisation de l'un ou l'autre maintiendra la connexion en vie
  • with ne crée pas de nouvelle portée, donc toutes les variables créées à l'intérieur de la suite de with seront accessibles à l'extérieur de celle-ci
  • Enfin, vous devez fermer la connexion manuellement

60voto

Roger Binns Points 1083

Pour répondre à la question spécifique de savoir ce qui se passe si vous ne fermez pas une base de données SQLite, la réponse est assez simple et s'applique à l'utilisation de SQLite dans n'importe quel langage de programmation. Lorsque la connexion est fermée explicitement par le code ou implicitement par la sortie du programme, toute transaction en cours est annulée. (Le retour en arrière est en fait effectué par le programme suivant qui ouvre la base de données.) S'il n'y a pas de transaction en cours, il ne se passe rien.

Cela signifie qu'il n'est pas nécessaire de s'inquiéter outre mesure de la fermeture de la base de données avant la sortie du processus, et qu'il convient de prêter attention aux transactions en veillant à les lancer et à les valider aux moments appropriés.

18voto

qarma Points 3310

Votre préoccupation sous-jacente est valable, mais il est également important de comprendre le fonctionnement de sqlite :

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

en termes de exactitude des données sqlite ne détient un verrou sur une base de données qu'à l'intérieur d'une transaction (*) ou de l'exécution d'une instruction.

Toutefois, en termes de gestion des ressources Par exemple, si vous prévoyez de supprimer un fichier sqlite ou d'utiliser un si grand nombre de connexions que vous risquez d'être à court de descripteurs de fichiers, vous devez également vous préoccuper des connexions ouvertes en dehors des transactions.

il y a deux façons de fermer une connexion : soit vous appelez .close() après quoi vous avez toujours un handle mais vous ne pouvez pas l'utiliser, ou vous laissez la connexion sortir de son champ d'application et être ramassée.

si vous doit fermer une connexion Le cas échéant, le fermer explicitement, conformément à la devise de Python " L'explicite vaut mieux que l'implicite ."

Si vous ne vérifiez le code que pour les effets de bord, laisser une dernière variable contenant une référence à la connexion sortir de la portée peut être acceptable, mais gardez à l'esprit que les exceptions capturent la pile, et donc les références dans cette pile. si vous transmettez des exceptions, la durée de vie de la connexion peut être prolongée de manière arbitraire.

programmateur de mise en garde sqlite utilise par défaut des transactions "différées", c'est-à-dire que la transaction ne démarre que lorsque vous exécutez une instruction. Dans l'exemple ci-dessus, la transaction s'exécute de 3 à 4, plutôt que de 2 à 4.

18voto

Vous pouvez utiliser un with bloc comme celui-ci :

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()
  • liens
  • démarre une transaction
  • crée un curseur de base de données
  • effectue l'opération et renvoie les résultats
  • ferme le curseur
  • valide ou annule la transaction
  • ferme la connexion

tous sûrs dans les cas heureux comme dans les cas exceptionnels

17voto

Voici le code que j'utilise. Le code Connection et le Cursor se fermera automatiquement grâce à contextlib.closing() . Les Connection sera automatiquement validée grâce au gestionnaire de contexte.

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)

1voto

elrado Points 1563

Votre version laisse conn dans le champ d'application après l'utilisation de la connexion.

EXEMPLE :

votre 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

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

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