Использование python с оператором «try» кроме блока - PullRequest
83 голосов
/ 04 сентября 2010

Является ли это правильным способом использовать оператор python «with» в сочетании с блоком try-exc?:

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

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

РЕДАКТИРОВАТЬ: идентичны ли функциональность вышеупомянутых двух блоков кода?

РЕДАКТИРОВАТЬ2: Первые несколько ответов обычно говорят о преимуществах использования «с», но здесь они кажутся незначительными. Мы все (или должны были) явно вызывать f.close () в течение многих лет. Полагаю, одно преимущество заключается в том, что неаккуратные кодировщики выиграют от использования «с».

Ответы [ 4 ]

125 голосов
/ 05 сентября 2010
  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())

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

6 голосов
/ 04 сентября 2010

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

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

1 голос
/ 04 сентября 2010

Я думаю, что вы неправильно поняли утверждение "with", которое сокращает только строки.Это на самом деле делает инициализацию и обрабатывает разрыв.

В вашем случае «с» открывает

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

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

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

0 голосов
/ 14 октября 2015

Более 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()
...