Это обычная идиома в python для использования диспетчера контекстов для автоматического закрытия файлов:
with open('filename') as my_file:
# do something with my_file
# my_file gets automatically closed after exiting 'with' block
Теперь я хочу прочитать содержимое нескольких файлов. Потребитель данных не знает и не заботится о том, поступают ли данные из файлов или нет файлов. Он не хочет проверять, могут ли объекты, которые он получил, открыть или нет. Он просто хочет получить что-то, чтобы читать строки. Поэтому я создаю итератор следующим образом:
def select_files():
"""Yields carefully selected and ready-to-read-from files"""
file_names = [.......]
for fname in file_names:
with open(fname) as my_open_file:
yield my_open_file
Этот итератор может использоваться следующим образом:
for file_obj in select_files():
for line in file_obj:
# do something useful
(Обратите внимание, что один и тот же код можно использовать, чтобы потреблять не открытые файлы, а списки строк - это круто!)
Вопрос: безопасно ли открывать открытые файлы?
Похоже, почему бы и нет? Потребитель вызывает итератор, итератор открывает файл, возвращает его потребителю. Потребитель обрабатывает файл и возвращается к итератору для следующего. Итерационный код возобновляется, мы выходим из блока "с", объект my_open_file
закрывается, переходит к следующему файлу и т.д.
Но что, если потребитель никогда не возвращается к итератору для следующего файла? F.E. исключение произошло внутри потребителя. Или потребитель нашел что-то очень интересное в одном из файлов и счастливо вернул результаты тому, кто его назвал?
В этом случае код Итератора никогда не возобновится, мы никогда не дойдем до конца с блоком, а объект my_open_file
никогда не будет закрыт!
Или это?