with update fetchmany error python sqlite3 database-connection

fetchmany - update sqlite3 python



¿Qué pasa si no cierro la conexión de base de datos en Python SQLite? (6)

Estoy haciendo algo como esto ...

conn = sqlite3.connect(db_filename) with conn: cur = conn.cursor() cur.execute( ... )

with automáticamente se confirman los cambios. Pero los doctores no dicen nada acerca de cerrar la conexión.

En realidad 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? ¿Y si lo dejo abierto?

EDITAR

Mis conclusiones ...

  • La conexión NO está cerrada en el administrador de contexto, lo he probado y confirmado. En __exit__ , el administrador de contexto SOLO realiza los cambios haciendo conn.commit()
  • with conn y with sqlite3.connect(db_filename) as conn son una y la misma cosa . Así que usar cualquiera de los dos mantendrá la conexión viva
  • with statement NO crea un nuevo ámbito, por lo tanto, todas las variables creadas dentro del conjunto de serán accesibles fuera de él
  • Finalmente, debes cerrar la conexión manualmente.

En respuesta a la pregunta específica de qué sucede si no cierra una base de datos SQLite, la respuesta es bastante simple y se aplica al uso de SQLite en cualquier lenguaje de programación. Cuando la conexión se cierra explícitamente por código o implícitamente por la salida del programa, cualquier transacción pendiente se revierte. (El programa siguiente realiza la reversión para abrir la base de datos). Si no hay ninguna transacción pendiente abierta, entonces no sucede nada.

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


Este es el código que uso. La Connection y el Cursor se cerrarán automáticamente gracias a contextlib.closing() . La Connection se comprometerá automáticamente gracias al gestor 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)


Para gestionar una conexión a una base de datos por lo general hago 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

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


Puedes usar un bloque with como este:

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

  • se conecta
  • comienza una transacción
  • crea un cursor db
  • Preforma la operación y devuelve los resultados.
  • cierra el cursor
  • confirma / revierte la transacción
  • cierra la conexión

Todo seguro en casos felices y excepcionales.


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

EJEMPLO:

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


Tiene una preocupación subyacente válida aquí, sin embargo, también es importante entender cómo funciona sqlite 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 , solo debe preocuparse por las transacciones y no abrir los identificadores. 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 administración de recursos , por ejemplo, si planea eliminar el archivo sqlite o utilizar tantas conexiones que podría quedarse sin descriptores de archivo, también le preocupa la posibilidad de abrir conexiones fuera de transacción.

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

Si debe cerrar una conexión , ciérrela explícitamente, de acuerdo con el lema de Python " explícito es mejor que implícito ".

Si solo está verificando el código para efectos secundarios, puede ser aceptable que la última variable que mantiene la referencia a la conexión quede fuera del alcance, pero tenga en cuenta que las excepciones capturan la pila y, por lo tanto, las referencias en esa pila. Si pasa las excepciones, la duración de la conexión puede extenderse arbitrariamente.

programador de advertencia , sqlite usa transacciones "diferidas" de forma predeterminada, es decir, la transacción solo comienza cuando se ejecuta una declaración. En el ejemplo anterior, la transacción se ejecuta de 3 a 4, en lugar de 2 a 4.