Ответ 1
Да, вы должны использовать context.closing()
; ваша собственная версия делает что-то совершенно другое.
Оператор with
позволяет менеджеру контекста знать, когда блок кода вводится и завершается; при выходе менеджер контекста также получает доступ к исключению, если это произошло. Файловые объекты используют это для автоматического закрытия файла при выходе из блока.
Функция connect_db()
из учебника возвращает sqlit3
соединения sqlit3
, который действительно может использоваться в качестве менеджера контекста. Однако метод connection.__exit__()
не закрывает соединение, он совершает транзакцию при успешном завершении или прерывает ее при возникновении исключения.
С другой стороны, контекстный менеджер contextlib.closing()
вызывает метод connection.close()
в соединении. Это совсем другое.
Таким образом, ваш второй фрагмент может работать, но делает что-то другое. Код учебника закрывает соединение, ваша версия совершает транзакцию. Вы уже вызываете db.commit()
, поэтому действие на самом деле избыточно, если никаких исключений не возникает.
Вы можете снова использовать соединение в качестве менеджера контекста, чтобы иметь возможность автоматического управления транзакциями:
def init_db():
with closing(connect_db()) as db:
with app.open_resource('schema.sql') as f, db:
db.cursor().executescript(f.read())
Обратите внимание , db
на втором with
линией, гарантируя, что метод db.__exit__()
вызывается при выходе из блока.