Подтвердить что ты не робот

Что делать, если я не закрываю соединение с базой данных в Python SQLite

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

conn = sqlite3.connect(db_filename)

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

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

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

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

EDIT

Мои выводы:

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

Ответ 1

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

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

Ответ 2

У вас есть основополагающая проблема здесь, однако также важно понять, как работает sqlite:

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

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

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

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

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

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

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

Ответ 3

Это код, который я использую. 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

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

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

Ответ 5

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

Пример:

ваша версия

    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)

Ответ 6

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

# 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

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