Зачем нам нужно предложение "finally" в Python?
Я не уверен, зачем нужны finally
на try...except...finally
заявления. На мой взгляд, этот блок кода
try:
run_code1()
except TypeError:
run_code2()
other_code()
то же самое с этим с помощью finally
:
try:
run_code1()
except TypeError:
run_code2()
finally:
other_code()
Я что-то пропустила?
11 ответов:
это имеет значение, если вы вернетесь рано:
try: run_code1() except TypeError: run_code2() return None # The finally block is run before the method returns finally: other_code()
сравнить с этим:
try: run_code1() except TypeError: run_code2() return None other_code() # This doesn't get run if there's an exception.
другие ситуации, которые могут вызвать различия:
- если исключение создается внутри блока except.
- если возникает исключение
run_code1()
но это неTypeError
.- другие операторы потока управления, такие как
continue
иbreak
заявления.
можно использовать
finally
чтобы убедиться, что файлы или ресурсы закрыты или освобождены независимо от того, происходит ли исключение, даже если вы не поймать исключение. (или если вы не поймать конкретные исключения.)myfile = open("test.txt", "w") try: myfile.write("the Answer is: ") myfile.write(42) # raises TypeError, which will be propagated to caller finally: myfile.close() # will be executed before TypeError is propagated
в этом примере вам было бы лучше использовать
with
заявление, но этот вид структуры может быть использован для других видов ресурсов.несколько лет спустя, я написал блоге о злоупотребление
finally
что читатели могут найти забавным.
Они не эквивалентны. Наконец, код выполняется независимо от того, что еще происходит. Это полезно для кода очистки, который должен выполняться.
блоки кода не эквивалентны. Элемент
finally
предложение также будет выполняться, еслиrun_code1()
создает исключение, отличное отTypeError
, илиrun_code2()
выдает исключение, в то время какother_code()
в первой версии не будет работать в этих случаях.
в вашем первом примере, что произойдет, если
run_code1()
вызывает исключение, а неTypeError
? ...other_code()
не будет выполнен.сравните это с
finally:
версия:other_code()
гарантированно будет выполняться независимо от любого возникшего исключения.
чтобы добавить к другим ответам выше,
finally
предложение выполняется независимо от того, что тогда какelse
предложение выполняется только в том случае, если исключение не было вызвано.например, при записи в файл без исключений будет выведено следующее:
file = open('test.txt', 'w') try: file.write("Testing.") print("Writing to file.") except IOError: print("Could not write to file.") else: print("Write successful.") finally: file.close() print("File closed.")
выход:
Writing to file. Write successful. File closed.
если есть исключение, код выведет следующее, (обратите внимание, что преднамеренная ошибка вызвана сохранение файла только для чтения.
file = open('test.txt', 'r') try: file.write("Testing.") print("Writing to file.") except IOError: print("Could not write to file.") else: print("Write successful.") finally: file.close() print("File closed.")
выход:
Could not write to file. File closed.
мы видим, что
finally
предложение выполняется независимо от исключения. Надеюсь, это поможет.
finally
для определения "очистить действия". Элементfinally
предложение выполняется в любом случае перед выходом изtry
оператор, произошло ли исключение (даже если вы его не обрабатываете) или нет.Я второй пример @Байерса.
наконец, можно также использовать, когда вы хотите запустить "необязательный" код перед запуском кода для своей основной работы, и этот необязательный код может потерпеть неудачу по разным причинам.
в следующем примере, мы не знаем точно, какие исключения
store_some_debug_info
могут кинуть.мы могли бы запустить:
try: store_some_debug_info() except Exception: pass do_something_really_important()
но большинство линтеров будут жаловаться на слишком расплывчатое исключение. Кроме того, поскольку мы выбираем просто
pass
по ошибки,except
блок не действительно добавить ценность.try: store_some_debug_info() finally: do_something_really_important()
приведенный выше код имеет тот же эффект, как и 1-й блок кода, но более лаконично.
прекрасный пример, как показано ниже:
try: #x = Hello + 20 x = 10 + 20 except: print 'I am in except block' x = 20 + 30 else: print 'I am in else block' x += 1 finally: print 'Finally x = %s' %(x)
как поясняется в документация на
finally
предложение предназначено для определения действий очистки, которые должны быть выполнены при всех обстоятельствах.если
finally
присутствует, он указывает обработчик "очистка". Элементtry
предложение выполняется, в том числе любоеexcept
иelse
положения. Если исключение возникает в любом из предложений и не обрабатывается, исключение-временно сохраняется. Элементfinally
пункт выполняется. Если существует сохраненное исключение, которое повторно вызывается в концеfinally
пункт.пример:
>>> def divide(x, y): ... try: ... result = x / y ... except ZeroDivisionError: ... print("division by zero!") ... else: ... print("result is", result) ... finally: ... print("executing finally clause") ... >>> divide(2, 1) result is 2.0 executing finally clause >>> divide(2, 0) division by zero! executing finally clause >>> divide("2", "1") executing finally clause Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in divide TypeError: unsupported operand type(s) for /: 'str' and 'str'
как вы можете видеть,
finally
пункт выполняется в любом случае. ЭлементTypeError
поднял путем деления двух строк не обрабатываетсяexcept
предложение и поэтому повторно подняты послеfinally
предложение было выполнено.в реальных приложениях предложение finally полезно для освобождения внешних ресурсов (таких как файлы или сетевые подключения), независимо от того, было ли использование ресурса успешным.
использование delphi профессионально в течение нескольких лет научило меня защищать мои процедуры очистки, используя, наконец,. Delphi в значительной степени обеспечивает использование finally для очистки любых ресурсов, созданных перед блоком try, чтобы не вызвать утечку памяти. Это также, как Java, Python и Ruby работает.
resource = create_resource try: use resource finally: resource.cleanup
и ресурс будет очищен независимо от того, что вы делаете между попробовать и наконец. Кроме того, он не будет очищен, если выполнение никогда не достигает
try
блок. (т. е. бросает исключение) это делает ваш код "исключений".А почему вы, собственно, нужен блок finally, не все языки. В C++, где вы автоматически вызываете деструкторы, которые принудительно очищают, когда исключение разворачивает стек. Я думаю, что это шаг в направлении более чистого кода по сравнению с try...наконец языки.
{ type object1; smart_pointer<type> object1(new type()); } // destructors are automagically called here in LIFO order so no finally required.