2012-03-05 9 views
42

sto facendo qualcosa di simile ...Che cosa succede se non chiudo la connessione al database in Python SQLite

conn = sqlite3.connect(db_filename) 

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

with impegna automaticamente le modifiche. Ma i documenti non dicono nulla sulla chiusura della connessione.

In realtà io posso usare conn in dichiarazioni successive (che ho testato). Quindi sembra che il gestore di contesto NON stia chiudendo la connessione.

Devo chiudere manualmente la connessione. Cosa succede se lo lascio aperto?

EDIT

Le mie conclusioni ...

  • Il collegamento non è chiusa nel contesto direttore, ho testato e confermato. Su __exit__, il manager contesto impegna solo le modifiche da fare conn.commit()
  • with conn e with sqlite3.connect(db_filename) as conn sono uno e la stessa cosa. Quindi, utilizzando sarà ancora mantenere la connessione viva
  • with dichiarazione non crea un nuovo ambito, quindi tutte le variabili create all'interno della suite di con saranno accessibili all'esterno
  • Infine, si dovrebbe chiudere la connessione manualmente
+0

Se lo si lascia aperto, rimane aperto fino a quando non viene eliminato dall'ambito e dalla garbage collection. A quel punto dovrebbe essere chiuso in modo sicuro (e credo che 'sqlite3' lo faccia). Ma meglio prevenire che curare. Chiudi le connessioni quando non le utilizzerai più. – Avaris

+0

È bello vedere un utente SO con 6 rappresentanti tornare e rispondere alle domande di risarcimento che ritengono non rispondano alla domanda. Un grande +1 lì. – Droogans

risposta

25

In risposta alla domanda specifica di che cosa succede se non si chiude un database SQLite, la risposta è abbastanza semplice e si applica all'uso di SQLite in qualsiasi lan di programmazione calibro. Quando la connessione viene chiusa esplicitamente dal codice o implicitamente dall'uscita del programma, viene annullata qualsiasi transazione in sospeso. (Il rollback viene effettivamente eseguito dal programma successivo per aprire il database.) Se non c'è nessuna transazione in sospeso aperta, non accade nulla.

Ciò significa che non è necessario preoccuparsi troppo di chiudere sempre il database prima dell'uscita del processo e di prestare attenzione alle transazioni assicurandosi di avviarle e impegnarsi in punti appropriati.

+2

Un lungo processo in esecuzione, come un'applicazione web, non ha chiusura implicita all'uscita, perché non esiste alcuna uscita. –

1

La versione lascia connessa dopo l'utilizzo della connessione.

ESEMPIO:

la versione

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 

nuova versione

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' non crea un nuovo ambito.] (Http://stackoverflow.com/questions/6432355/variable-defined-with-with-statement-available-outside-of-with-block)' conn' sarà disponibile dopo il 'con' in entrambi i casi. – Avaris

6

avete una preoccupazione di fondo valida qui, ma è anche importante capire come SQLite funziona troppo:

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

in termini di dati correttezza, avete solo bisogno di preoccuparsi di transazioni e maniglie non aperti. sqlite contiene solo un blocco su un database all'interno di una transazione (*) o l'esecuzione di una dichiarazione.

tuttavia in termini di gestione delle risorse , ad es. se si pianifica di rimuovere il file sqlite o di utilizzare così tante connessioni, è possibile che i descrittori di file vengano a mancare, ma si preoccupano anche delle connessioni aperte alla transazione.

Ci sono due modi in cui una connessione è chiusa: o si chiama .close() in modo esplicito, dopo di che si ha ancora un handle ma non si può usare, o si lascia la connessione fuori portata e si ottiene la raccolta di dati inutili.

se necessario chiudere una connessione, chiuderlo in modo esplicito, secondo il motto di Python "esplicito è meglio che implicita."

se si sta controllando solo il codice per gli effetti collaterali, lasciare che un'ultima variabile contenente il riferimento alla connessione esca dall'ambito può essere accettabile, ma si tenga presente che le eccezioni catturano lo stack e quindi i riferimenti in tale pila. se si passano eccezioni, la durata della connessione può essere estesa arbitrariamente.

programmatore di avvertenza, sqlite utilizza le transazioni "posticipate" per impostazione predefinita, ovvero la transazione inizia solo quando si esegue un'istruzione. Nell'esempio di cui sopra, di transazione va da 3 a 4, piuttosto che da 2 a 4.

1

Per la gestione di una connessione a un database di solito faccio questo,

# 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 

così facendo, sono sicuro che la connessione è esplicitamente chiusa.

+2

non chiude la connessione in caso di eccezione generata –

2

È possibile utilizzare un blocco with come questo:

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() 
  • collega
  • avvia una transazione
  • crea un cursore db
  • preforme l'operazione e restituisce i risultati
  • Chiude il cursore
  • si impegna/Rotoli-back della transazione
  • chiude la connessione

tutti sicuri in entrambi i casi felici ed eccezionali

3

Questo è il codice che uso. Lo Connection e lo Cursor si chiuderanno automaticamente grazie a contextlib.closing(). Il Connection si impegnerà automaticamente grazie al gestore di contesto.

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) 
Problemi correlati