2012-03-05 39 views
42

que estoy haciendo algo como esto ...¿Qué pasa si no cierra la conexión de base de datos SQLite en Python

conn = sqlite3.connect(db_filename) 

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

with comete automáticamente los cambios. Pero los documentos no dicen nada acerca de cerrar la conexión.

Actualmente puedo usar conn en declaraciones posteriores (que he probado). Por lo tanto, parece que el administrador de contexto NO está cerrando la conexión.

Tengo que cerrar manualmente la conexión. ¿Qué pasa si lo dejo abierto?

EDITAR

Mis conclusiones ...

  • La conexión no está cerrada en el gestor de contexto, he probado y confirmado. Al __exit__, el gestor de contexto compromete únicamente a los cambios por hacer conn.commit()
  • with conn y with sqlite3.connect(db_filename) as conn son una y la misma cosa. Así, utilizando ya sea seguirá siendo mantener la conexión viva
  • with declaración no crear un nuevo ámbito, por lo que todas las variables creadas dentro de la suite de la será accesible fuera de ella
  • Por último, se debe cerrar la conexión manualmente
+0

Si lo deja abierto, permanece abierto hasta que se sale del alcance y de la recolección de basura. En ese punto, podría cerrarse de manera segura (y creo que 'sqlite3' hace eso). Pero es mejor estar a salvo que lamentar. Cierre sus conexiones cuando ya no las use. – Avaris

+0

Es bueno ver a un usuario de SO con 6 repeticiones y contestar las respuestas que sienten que no están respondiendo la pregunta. Un gran +1 allí. – Droogans

Respuesta

25

En respuesta a la pregunta específica de lo que sucede si no se cierra una base de datos SQLite, la respuesta es bastante simple y se aplica al uso de SQLite en cualquier lan de programación guage Cuando la conexión se cierra explícitamente por código o implícitamente por la salida del programa, se retrotrae cualquier transacción pendiente. (La retrotracción se realiza en realidad en el siguiente programa para abrir la base de datos). Si no hay ninguna transacción pendiente abierta, no ocurre nada.

Esto significa que no tiene que preocuparse demasiado por cerrar siempre la base de datos antes de la salida del proceso, y que debe prestar atención a las transacciones y asegurarse de iniciarlas y confirmarlas en los puntos apropiados.

+2

Un proceso de larga ejecución, como una aplicación web, no tiene cierre implícito al salir, porque no hay salida. –

1

Su versión deja conn en alcance después del uso de la conexión.

Ejemplo:

su versión

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 

nueva versión

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) 
+13

['with' no crea un nuevo alcance]] (http://stackoverflow.com/questions/6432355/variable-defined-with-with-statement-available-outside-of-with-block)' conn' será disponible después del 'con' en ambos casos. – Avaris

6

que tenga un problema subyacente válido aquí, sin embargo también es importante entender cómo sqlite opera también:

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

en cuanto a la corrección de los datos , sólo tendrá que preocuparse de las transacciones y los mangos no abiertos. sqlite solo mantiene un bloqueo en una base de datos dentro de una transacción (*) o ejecución de declaración.

sin embargo, en términos de gestión de recursos, p. Si planea eliminar el archivo sqlite o usar tantas conexiones, es posible que se quede sin descriptores de archivo, también se preocupa de abrir las conexiones fuera de la transacción.

hay dos formas en que se cierra una conexión: o llama al .close() explícitamente, después de lo cual todavía tiene un identificador pero no puede usarlo, o deja que la conexión salga del alcance y se recoja basura.

si debe cerrar una conexión, cerrarla de forma explícita, de acuerdo con el lema de Python "explícita es mejor que implícito." si solo está revisando el código de efectos secundarios, puede ser aceptable dejar una última referencia de tenencia de la variable fuera de alcance, pero tenga en cuenta que las excepciones capturan la pila y por lo tanto las referencias en esa pila. si pasa excepciones, la duración de la conexión se puede extender arbitrariamente.

programador de advertencias, sqlite utiliza las transacciones "diferidas" de forma predeterminada, es decir, la transacción solo se inicia cuando se ejecuta una instrucción. En el ejemplo anterior, la transacción va de 3 a 4, en lugar de desde 2 a 4.

1

Para la gestión de una conexión con una base de datos que suelo hacer esto,

# 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 

hacerlo, estoy seguro de que la conexión está explícitamente cerrada.

+2

no cierra la conexión en caso de que se rechace una excepción –

2

Se puede utilizar un bloque de with así:

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() 
  • conecta
  • inicia una transacción
  • crea un cursor db
  • preformas la operación y devuelve los resultados
  • cierra el cursor
  • commits/Rolls-la transacción
  • cierra la conexión

todos a salvo, en ambos casos excepcionales felices y

3

Este es el código que utilizo. El Connection y el Cursor se cerrarán automáticamente gracias al contextlib.closing(). El Connection se confirmará automáticamente gracias al administrador de contexto.

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) 
Cuestiones relacionadas