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

Правильно ли это использовать оператор python с инструкцией в сочетании с блоком 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" здесь, что мы можем избавиться от трех строк кода? Мне кажется, что это не убедительно для меня для этого случая использования (хотя я понимаю, что оператор "с" имеет другие применения).

EDIT: Является ли функциональность этих двух блоков кода одинаковой?

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

Ответ 1

  • Два кода, которые вы указали, не эквивалент
  • Код, который вы описали как старый способ от того, что происходит, имеет серьезную ошибку: в случае открытия файла вам не удастся получит второе исключение в 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 на внутренних уровнях.

Ответ 2

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

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

Ответ 3

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

В вашем случае "с" делает

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

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

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

Ответ 4

Чем больше Pythonic способ для следующих кодов:

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()