Использование оператора python "with" с блоком try-except

правильно ли использовать оператор python "with" в сочетании с блоком try-except?:

try:
    with open("file", "r") as f:
        line = f.readline()
except IOError:
    <whatever>

Если это так, то, учитывая старый способ делать вещи:

try:
    f = open("file", "r")
    line = f.readline()
except IOError:
    <whatever>
finally:
    f.close()

является ли основным преимуществом оператора "with" здесь, что мы можем избавиться от трех строк кода? Это не кажется мне убедительным для этого случая использования (хотя я понимаю, что оператор "with" имеет другие применения).

EDIT: является ли функциональность из вышеперечисленных двух блоков кода идентичны?

EDIT2: первые несколько ответов говорят в основном о преимуществах использования "С", но здесь они кажутся маргинальными. Мы все были (или должны были быть) явным вызовом f.закрыть() в течение многих лет. Я полагаю, что одно из преимуществ заключается в том, что небрежные кодеры выиграют от использования "с".

4 ответов


  1. два блока кода, которые вы дали не эквивалентно
  2. код, который вы описали как старый способ делать вещи серьезная ошибка: в случае открытия файла не удается получит второе исключение в finally пункт, потому что f - это не связанный.

эквивалентный код старого стиля будет:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

Как видите,with заявление может сделать вещи менее подвержены ошибкам. В новых версиях Python (2.7, 3.1), вы также можете комбинировать несколько выражений в одном with заявление. Например:

with open("input", "r") as inp, open("output", "w") as out:
    out.write(inp.read())

кроме того, я лично считаю плохой привычкой ловить любое исключение как можно раньше. Это не является целью исключений. Если функция ввода-вывода, которая может потерпеть неудачу, является частью более сложной операции, в большинстве случаев IOError должен прервать всю операцию и поэтому обрабатываться на внешнем уровне. Используя with заявления, вы можете избавиться от всех этих try...finally высказывания на внутренних уровнях.


если содержание finally block определяются свойствами открываемого объекта file, почему бы исполнителю объекта file не написать finally заблокировать? это пользу with оператор, гораздо больше, чем сохранение трех строк кода в этом конкретном случае.

и да, то, как вы объединили with и try-except в значительной степени единственный способ сделать это, так как исключительные ошибки, вызванные в open само утверждение не может быть поймано в with блок.


Я думаю, вы неправильно поняли утверждение "С", что оно только уменьшает строки. Он фактически выполняет инициализацию и обрабатывает teardown.

в вашем случае "с" не

  • открыть файл,
  • обработать его содержимое и
  • убедитесь, что закрыть его.

вот ссылка для понимания" с " утверждение:http://effbot.org/zone/python-with-statement.htm

Edit: Да, ваше использование" с" корректность и функциональность обоих блоков кода одинаковы. Вопрос о том, почему использовать "с" ? это из-за преимуществ, которые вы получаете с ним. как вы упомянули о случайно пропавшем Ф. закрыть().


более подходящие для Python способ для следующих кодов:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

try:
    f = open("file", "r")
except IOError:
    <whatever>
else:
    f.close()