Закройте базу данных sqlite3 при выходе, несмотря ни на что

В настоящее время я пишу скрипт, который использует sqlite3. Недавно я столкнулся с проблемой, связанной с тем, что база данных используется другой программой из-за того, что мой код преждевременно завершает работу с ошибкой.

При подобных проблемах обычно используют:

conn = sqlite3.connect(...)
try:
    #Do stuff
finally:
    conn.close()

Но это не сработает в моем случае. Вкратце, это мой код:

импортировать sqlite3

class Thingamadoodle:
    def __init__(self, ...):
        self.conn = sqlite3.connect(...)
        ...

    #Methods and stuff

    def __del__(self):
        self.conn.close()

poop = Thingamadoodle(...)
poop.do_stuff(...)
poop.throw_irritating_exception_that_you_cant_track_down(irritatingness=11)

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

Есть ли способ безопасно закрыть соединение даже при нечистом выходе?


person Cheezey    schedule 16.11.2013    source источник
comment
@ hus787 Спасибо, я воспользуюсь этим, но я все еще не думаю, что это решит мою проблему. Он защищает от повреждения, но не закрывает базу данных.   -  person Cheezey    schedule 16.11.2013


Ответы (1)


Честно говоря, я не очень понимаю вопрос, но почему бы просто не обернуть poop.do_stuff() в блок try/except?

try:
    poop.do_stuff()
except:
    poop.__del__()
finally:
    poop.__del__()

Или, чтобы быть немного чище, используйте менеджер контекста:

class Thingamadoodle:
    def __init__(self, ...):
        ...

    #Methods and stuff
    def __enter__(self):
        self.conn = sqlite3.connect(...)
        return self
    def __exit__(self, errorType, errorValue, errorTrace):
        self.conn.close()

И просто выполните его как:

with Thingmadoodle(args) as poop:
    #do things

После того, как весь код будет выполнен, или после того, как в операторе произошло исключение, __exit__ будет выполнено, и его можно будет смело закрывать.

Надеюсь это поможет!

person aIKid    schedule 16.11.2013
comment
Я думаю, что мог бы, но я действительно не хочу загромождать свой код ими. - person Cheezey; 16.11.2013
comment
Спасибо! Это намного чище, и, насколько мне известно, я также могу передавать poop функциям, не выходя из контекстного менеджера. Правильно? - person Cheezey; 16.11.2013
comment
Да, пока он находится в блоке with. - person aIKid; 16.11.2013