2016-09-20 2 views
1

Этот вопрос исключительно из любопытства. В недавнем обсуждении вопроса here, я часто задавался вопросом, почему менеджер контекста (with) не выдает ошибку, когда люди явно закрывают файл в любом случае из-за недопонимания ... и затем я обнаружил, что вы можете позвонить close() на файл несколько раз без ошибок, даже без использования with.Почему вы можете закрыть() файл-объект более одного раза?

Единственное, что мы можем найти в связи с этим является here и просто вкрадчиво говорит (курсив мой):

близко()
Закройте файл. Закрытый файл больше не может быть прочитан или написан. Любая операция, которая требует, чтобы файл был открыт, поднимет значение ValueError после того, как файл будет закрыт. Адрес: close() не один раз.

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

+0

Возможно, если код был немного неаккуратным и имел 'close()' в нескольких местах, а не отслеживал состояние файла по всему ... по крайней мере, ваш код не выдавал бы исключения. – haliphax

+1

Ha! Ты подтолкнул меня на это! Я в середине составляю почти идентичный вопрос, и просто увидел, что это всплывает как связанный вопрос. Я буду повышать вместо этого;) – elethan

+0

@elethan Я как раз собирался сообщить вам в другой теме: P – roganjosh

ответ

2
  1. Думать о with просто неправильно. Такое поведение было в Python forever, и поэтому стоит сохранить его для обратной совместимости.

  2. Потому что это нецелесообразно возбуждать исключение. Если у вас есть реальная ошибка в коде, где вы можете закрыть файл до его окончания, вы получите исключение при использовании операций read или write в любом случае, и, таким образом, вы никогда не достигнете второго звонка до close.

  3. Разрешение редко сделать код более удобным для записи, избегая добавления большого количества if not the_file.isclosed(): the_file.close().

  4. BDFL создал объекты файла таким образом, и мы придерживаемся такого поведения, поскольку нет никаких оснований для его изменения.

+0

'the_file.closed';) – elethan

3

Управление ресурсами - это большое дело. Это часть причины, по которой у нас есть менеджеры контекста.

Я думаю, что основная группа разработчиков подумала, что лучше сделать так, чтобы это было «безопасно», чтобы позвонить близко друг к другу, чтобы побудить людей закрыть свои файлы. В противном случае вы можете попасть в ситуацию, когда вы спрашиваете: «Было ли это закрыто раньше?». Если .close() нельзя было вызывать несколько раз, единственным вариантом было бы поместить ваш вызов file.close() в пункт /except. Это делает код более уродливым и (честно говоря), многие люди, вероятно, просто удалят вызов file.close(), а не обрабатывают его должным образом. В этом случае удобно просто позвонить file.close(), не беспокоясь о каких-либо последствиях, так как это почти наверняка преуспеет и оставляет вас с файлом, который, как вы знаете, закрыт после этого.

0

Вызов функции выполнил свое обещание - после вызова его файл закрыт.Это не похоже на что-то не удалось, вам просто не нужно ничего делать, чтобы обеспечить условие, о котором вы просите.

+0

Я не уверен, что понимаю этот ответ. Я спрашивал больше о вызовах 'close()' на то, что уже закрыто, как правило, приводит к исключению, но это не относится к закрытому файловому объекту – roganjosh

+0

@roganjosh? должен 'dict_instance.clear()' вызвать исключение, если dict уже был пуст (потому что «нет ничего, чтобы очистить»)? Экземпляры будут пустыми после вызова функции, и это все, что запрашивает абонент. Иногда делать ничего не достаточно, чтобы пройти тест. Кроме того, что ваш источник на _it обычно приводит к исключению_? –

+0

Я не уверен, где это происходит, другие ответы были довольно ясными. Попробуйте закрыть курсор на закрытом подключении к базе данных 'sqlite3'. Вы говорите, что нет ничего необычного в том, что вы можете сделать _nothing_ для объекта 'closed', кроме как' close() 'его второй раз? – roganjosh

Смежные вопросы