Python с оператором ', я должен использовать contextlib.closing?
from contextlib import closing
def init_db():
with closing(connect_db()) as db:
with app.open_resource('schema.sql') as f:
db.cursor().executescript(f.read())
db.commit()
Это из учебного пособия по колбе, шаг 3 ( http://flask.pocoo.org/docs/tutorial/dbinit/). И мне немного любопытно насчет 4-й строки этого.
Должен ли я импортировать и использовать этот метод contextlib.closing()?
Когда я узнал об операторе Statement, во многих статьях говорилось, что он автоматически закрывает файл после процесса, как показано ниже.
with open('filename','w') as f:
f.write(someString);
Даже если я не использую этот contextlib.closing(), как показано ниже, какая разница? Это с версии 2.7.6, спасибо.
def init_db():
with connect_db() as db:
with app.open_resource('schema.sql') as f:
db.cursor().executescript(f.read())
db.commit()
2 ответа
Да, вы должны использовать context.closing()
; ваша собственная версия делает что-то совсем другое.
with
оператор позволяет диспетчеру контекста знать, когда блок кода вводится и выходит; при выходе диспетчеру контекста также предоставляется доступ к исключению, если оно произошло. Файловые объекты используют это для автоматического закрытия файла при выходе из блока.
connect_db()
Функция из учебника возвращает 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__()
метод вызывается при выходе из блока.
Единственное, что сделано with
заявление позвонить __enter__
метод перед входом в свой блок и __exit__
метод, прежде чем выйти из него. Если эти методы не определены, with
заявление не будет работать, как вы можете ожидать. Я не знаю, какой тип возврата connect_db
, но я предполагаю, что это может быть много разных вещей из разных сторонних библиотек. Итак, ваш код без closing
вероятно, будет работать во многих (всех?) случаях, но вы никогда не знаете, что может быть возвращено connect_db
,