Гарантированное закрытие файлов: обработчики исключений и менеджеры контекста

garantirovannoe zakrytie fajlov obrabotchiki iskljuchenij i menedzhery konteksta Инструменты для работы с файлами и каталогами

Операция закрытия файла вручную оформляется в программном коде очень просто, но как гарантировать закрытие файла в случае исключения, которое может отбросить поток выполнения программы далеко от того места, где находится вызов метода close? Прежде всего, не забывайте, что файлы закрываются сами, когда соответствующие им объекты файлов утилизируются сборщиком мусора, причем это произойдет в любом случае, даже если возникнет исключение.

Однако если необходимо обеспечить явное закрытие файла в любом случае, у вас есть два пути: наиболее типичный — использование инструкции try с предложением finally, потому что оно позволяет реализовать выполнение заключительных операций для любых типов исключений:

myfile = open(filename, ‘w’) try:

обработка myfile

finally:

myfile.close()

В последних версиях Python появилась инструкция with, обеспечивающая более краткий способ реализации заключительных операций для объектов определенных типов, включая закрытие файлов:

with open(filename, ‘w’) as myfile:

… обработка myfile, закрывается автоматически после выхода…

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

Решение на основе инструкции with выглядит заметно короче (на 3 строки), чем альтернативное решение на основе конструкции try/finally, но оно является менее универсальным — инструкция with может применяться только к объектам, поддерживающим протокол менеджеров контекста, тогда как конструкция try/finally позволяет реализовать произвольные заключительные операции для произвольных контекстов исключений. Область применения инструкции with ограничена, несмотря на то, что у некоторых типов объектов также имеются менеджеры контекста (например, у блокировок потоков). Если вам хочется помнить только один вариант реализации заключительных операций, то конструкция try/finally выглядит наиболее объемлющей. При этом инструкция with позволяет уменьшить объем программного кода для файлов, которые должны быть закрыты в любом случае, и прекрасно справляется с этой конкретной задачей. Она позволяет сэкономить строку программного кода, когда обработка исключений не предусматривается (хотя и за счет добавления в логику обработки файла еще одного уровня вложенности и отступов):

myfile = open(filename, ‘w’) # традиционная форма

…обработка myfile

myfile.close()

with open(filename) as myfile: # с применением менеджера контекста … обработка myfile

В версии Python 3.1 и выше эта инструкция позволяет указывать несколько (то есть вложенные) менеджеров контекста — в инструкции можно перечислить через запятую любое количество менеджеров контекста, и она будет действовать, как набор вложенных друг в друга инструкций with. В общем случае в версии 3.1 и выше следующий программный код:

with A() as a, B() as b: инструкции

действует так же, как программный код ниже, который можно использовать в версиях 3.1, 3.0 и 2.6:

with A() as a:

with B() as b:

…инструкции…

Например, когда программа выходит из следующего блока инструкции with, автоматически выполняются действия по закрытию обоих файлов, независимо от того, возникло исключение или нет:

with open(‘data’) as fin, open(‘results’, ‘w’) as fout: for line in fin:

fout.write(transform(line))

В последние годы такой программный код, опирающийся на использование менеджеров контекста, становится все более привычным, причем отчасти благодаря приходу новых программистов из языков, требующих вручную закрывать файлы в любых случаях. В большинстве ситуаций нет никакой необходимости обертывать инструкциями with программный код обработки файлов — часто бывает вполне достаточно того, что объекты файлов автоматически закрываются при утилизации, а для других ситуаций достаточно вручную вызывать метод close. Приемы, основанные на использовании инструкций with и try, описанные выше, следует использовать только в случае необходимости явно закрывать файлы и только, когда существует вероятность исключений. Поскольку стандартная реализация C Python автоматически закрывает файлы при утилизации объектов, во многих (если не в большинстве) ситуациях ни один из приведенных вариантов не является необходимым.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий