Что если я не закрою соединение с базой данных в Python SQLite - PullRequest
54 голосов
/ 05 марта 2012

Я делаю что-то вроде этого ...

conn = sqlite3.connect(db_filename)

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

with автоматически фиксирует изменения.Но документы ничего не говорят о закрытии соединения.

На самом деле я могу использовать conn в более поздних утверждениях (которые я проверял).Следовательно, кажется, что менеджер контекста НЕ закрывает соединение.

Нужно ли закрывать соединение вручную.Что если я оставлю его открытым?

РЕДАКТИРОВАТЬ

Мои выводы ...

  • Соединение НЕ закрыто в менеджере контекста я проверил и подтвердил это.После __exit__ менеджер контекста ТОЛЬКО фиксирует изменения, выполнив conn.commit()
  • with conn и with sqlite3.connect(db_filename) as conn равны одно и то же .Таким образом, использование любого из них по-прежнему будет поддерживать соединение в действии * Оператор 1029 *
  • with НЕ создает новую область видимости, следовательно, все переменные, созданные в наборе with, будут доступны за его пределами
  • Наконец, выследует закрыть соединение вручную

Ответы [ 6 ]

32 голосов
/ 08 марта 2012

В ответ на конкретный вопрос о том, что произойдет, если вы не закроете базу данных SQLite, ответ довольно прост и применим к использованию SQLite на любом языке программирования. Когда соединение закрывается явно кодом или неявно завершением программы, тогда любая ожидающая транзакция откатывается. (Откат фактически выполняется следующей программой для открытия базы данных.) Если нет открытых транзакций, то ничего не происходит.

Это означает, что вам не нужно слишком беспокоиться о том, чтобы всегда закрывать базу данных перед завершением процесса, и что вы должны обращать внимание на транзакции, обязательно запуская их и фиксируя в соответствующих точках.

9 голосов
/ 04 октября 2013

Здесь у вас есть действительная основополагающая проблема, однако также важно понять, как работает sqlite:

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

с точки зрения правильности данных , вам нужно беспокоиться только о транзакциях, а не об открытых дескрипторах. sqlite только блокирует базу данных внутри транзакции (*) или выполнения оператора.

однако с точки зрения управления ресурсами , например если вы планируете удалить файл sqlite или использовать так много соединений, что у вас могут не хватить файловых дескрипторов, вам не безразличны и открытые соединения вне транзакции.

существует два способа закрытия соединения: либо вы вызываете .close() явно, после чего у вас все еще есть дескриптор, но не можете его использовать, либо вы позволяете соединению выйти из области видимости и получить сборщик мусора.

если вы должны закрыть соединение , закройте его явно, согласно девизу Python " явно лучше, чем неявное ."

Если вы проверяете код только на наличие побочных эффектов, выход последней переменной, содержащей ссылку на соединение, может быть приемлемым, но имейте в виду, что исключения захватывают стек, и, следовательно, ссылки в этом стеке. если вы передаете исключения, время жизни соединения может быть произвольно продлено.

caveat programmator , sqlite по умолчанию использует «отложенные» транзакции, то есть транзакция начинается только при выполнении оператора. В приведенном выше примере транзакция выполняется с 3 до 4, а не с 2 до 4.

5 голосов
/ 27 ноября 2017

Это код, который я использую.Connection и Cursor автоматически закроются благодаря contextlib.closing().Connection будет автоматически зафиксирован благодаря диспетчеру контекста.

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)
4 голосов
/ 02 октября 2017

Вы можете использовать блок with следующим образом:

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()
  • соединяет
  • начинает транзакцию
  • создает курсор в БД
  • выполняет операцию и возвращает результаты
  • закрывает курсор
  • фиксирует / откатывает транзакцию
  • закрывает соединение

все безопасно как в счастливых, так и в исключительных случаях

0 голосов
/ 16 февраля 2017

Для управления соединением с базой данных я обычно делаю это,

# 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

делая это, я уверен, что соединение явно закрыто.

0 голосов
/ 05 марта 2012

Ваша версия оставляет коннект в области действия после использования соединения.

Пример:

ваша версия

    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

новая версия

    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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...