Является ли хорошим тоном перебирать файл, используя только цикл for?

Я наткнулся на код, который выполняет итерацию по строкам в файле, например:

for line in open(filename, 'r'):
    do_all_the_things()

Это более питоническая версия чего-то вроде:

with open(filename, 'r') as f:
    for line in f:
        do_all_the_things()

Он использует меньше уровней отступов, поэтому выглядит лучше, но это то же самое? Насколько я знаю, with в основном добавляет finally: f.close() или что-то в этом роде, чтобы гарантировать, что после выхода из блока объект будет очищен. Когда первый for цикл заканчивается (или, возможно, прерывается с break) и переменная выходит за пределы области видимости, происходит ли то же самое? Могу ли я взять подсказку из первого бита кода и сэкономить несколько нажатий клавиш, или, скорее, следует ли мне это исправить?


person Nick T    schedule 19.04.2013    source источник
comment
возможный дубликат Python: важно ли явное закрытие файлов? Также относится к: http://stackoverflow.com/questions/575278/how-does-python-close-files-that-have-been-gced   -  person Bakuriu    schedule 19.04.2013


Ответы (2)


Вы не создаете никаких ссылок на файловый объект, кроме итератора, используемого циклом for.

Это означает, что как только цикл for завершится, счетчики ссылок этого итератора, а затем и файлового объекта будут равны нулю, и они будут удалены.

Когда файловый объект удаляется, он закрывается.

Таким образом, вы не оставляете открытые файлы, используя простой цикл for.

Тем не менее, в более крупной программе хорошо быть явным - и оператор with ясно говорит, что файл используется только в этом контексте.

Лично, если я открываю файл для записи / добавления, я буду использовать with, даже если я использую его только в одном месте. Если я просто открываю его для чтения, а не создаю явную ссылку, я просто использую объект напрямую.

person agf    schedule 19.04.2013
comment
Пример в документации для file.close кажется < / i> не соглашаться с вами. - person Bakuriu; 19.04.2013
comment
Таким образом, вы не оставляете открытые файлы, используя простой цикл for. Это может быть правдой в Cpython, но определенно не гарантируется спецификацией. - person mgilson; 19.04.2013
comment
@mgilson Я в курсе. Если бы мне были нужны гарантии, я бы использовал скомпилированный язык с настоящей системой типов; В большинстве случаев я совершенно доволен максимальными усилиями, особенно если процесс Python недолговечен, поэтому вам все равно не нужно беспокоиться об утечке дескрипторов файлов. - person agf; 19.04.2013
comment
@Bakuriu Это разница между гарантией и реальностью сборки мусора в каждой реализации Python. Я описываю то, что происходит при всех нормальных обстоятельствах, а не то, что произойдет гарантированно. - person agf; 19.04.2013

Обязательно используйте диспетчер контекста. Это единственный способ гарантировать правильность обработки вашего файлового объекта.

Хотя первая версия, скорее всего, не вызовет никаких проблем в Cpython (в настоящее время), в спецификации никогда не указывается, когда (или даже если) вызывается __del__. Из-за этого вы не можете знать наверняка, что ваш файловый объект когда-либо будет должным образом завершен с использованием первой версии.

person mgilson    schedule 19.04.2013