Python exception handling using try, except and finally statement

8.6. Определение очищающих действий

Оператор try (docs.python.org/3/reference/compound_stmts.html#try) имеет другую дополнительную ветку, которая предназначена для определения clean-up (очищающих — прим. пер.) действий, которые должны быть выполнены при любых обстоятельствах. Например:

Содержимое finally всегда выполняется перед выходом из конструкции try, независимо от того произошло исключение или нет. Когда исключение произошло в ветке try и не было обработано в ветке except (или оно произошло в ветках except или else), оно будет вызвано снова после того, как выполнится содержимое finally. Ветка finally также выполняется «на выходе», когда из любой ветки всего оператора try выход осуществляется через операторы break, continue или return. Более сложный пример:

Как вы можете видеть, ветка finally выполняется в любом случае. TypeError возникшее из-за деления двух строк не обрабатывается веткой except и поэтому перевызывается после того, как ветка finally была выполнена.

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

Перехват определенных исключений в Python

В предыдущем примере мы не специфицировали перехватываемые исключения в блоке .

С практической точки зрения это нездорово, так как мы будем все исключения обрабатывать одинаково. Но мы можем определить, какие именно исключения мы будем перехватывать, и как мы их будем обрабатывать.

Для обработки различных исключений у одной инструкции может быть сколько угодно блоков , но выполнен будет только тот, который соответствует перехваченному исключению.

Чтобы определить несколько исключений для одного блока , мы можем использовать кортеж из значений исключений. Вот примерный псевдокод:

try:
   # do something
   pass

except ValueError:
   # handle ValueError exception
   pass

except (TypeError, ZeroDivisionError):
   # handle multiple exceptions
   # TypeError and ZeroDivisionError
   pass

except:
   # handle all other exceptions
   pass

Задания для самоподготовки

1. Напишите
программу ввода натуральных чисел через запятую и преобразования этой строки в
список целых чисел. (Используйте здесь функцию map для
преобразования элементов последовательности строк в последовательность чисел).
Реализовать обработку возможных исключений при таком преобразовании.

2. Написать
функцию вычисления среднего арифметического элементов переданного ей списка.
Реализовать обработку возможных исключений при ее работе.

3. Написать
функцию-генератор (с использованием оператора yield) для удаления
произвольного элемента из множества (с помощью метода pop()). Функция
должна возвращать значение удаленного элемента. Реализовать обработку возможных
исключений при ее работе.

Видео по теме

Python 3 #1: установка и запуск интерпретатора языка

Python 3 #2: переменные, оператор присваивания, типы данных

Python 3 #3: функции input и print ввода/вывода

Python 3 #4: арифметические операторы: сложение, вычитание, умножение, деление, степень

Python 3 #5: условный оператор if, составные условия с and, or, not

Python 3 #6: операторы циклов while и for, операторы break и continue

Python 3 #7: строки — сравнения, срезы строк, базовые функции str, len, ord, in

Python 3 #8: методы строк — upper, split, join, find, strip, isalpha, isdigit и другие

Python 3 #9: списки list и функции len, min, max, sum, sorted

Python 3 #10: списки — срезы и методы: append, insert, pop, sort, index, count, reverse, clear

Python 3 #11: списки — инструмент list comprehensions, сортировка методом выбора

Python 3 #12: словарь, методы словарей: len, clear, get, setdefault, pop

Python 3 #13: кортежи (tuple) и операции с ними: len, del, count, index

Python 3 #14: функции (def) — объявление и вызов

Python 3 #15: делаем «Сапер», проектирование программ «сверху-вниз»

Python 3 #16: рекурсивные и лямбда-функции, функции с произвольным числом аргументов

Python 3 #17: алгоритм Евклида, принцип тестирования программ

Python 3 #18: области видимости переменных — global, nonlocal

Python 3 #19: множества (set) и операции над ними: вычитание, пересечение, объединение, сравнение

Python 3 #20: итераторы, выражения-генераторы, функции-генераторы, оператор yield

Python 3 #21: функции map, filter, zip

Python 3 #22: сортировка sort() и sorted(), сортировка по ключам

Python 3 #23: обработка исключений: try, except, finally, else

Python 3 #24: файлы — чтение и запись: open, read, write, seek, readline, dump, load, pickle

Python 3 #25: форматирование строк: метод format и F-строки

Python 3 #26: создание и импорт модулей — import, from, as, dir, reload

Python 3 #27: пакеты (package) — создание, импорт, установка (менеджер pip)

Python 3 #28: декораторы функций и замыкания

Python 3 #29: установка и порядок работы в PyCharm

What are exceptions in Python?

Python has built-in exceptions which can output an error. If an error occurs while running the program, it’s called an exception.

If an exception occurs, the type of exception is shown. Exceptions needs to be dealt with or the program will crash. To handle exceptions, the block is used.

Some exceptions you may have seen before are , or but there are many more.

All exceptions in Python inherit from the class BaseException. If you open the Python interactive shell and type the following statement it will list all built-in exceptions:

The idea of the try-except clause is to handle exceptions (errors at runtime). The syntax of the try-except block is:

1234
try:    <do something>except Exception:    <handle the error>

The idea of the try-except block is this:

  • try: the code with the exception(s) to catch. If an exception is raised, it jumps straight into the except block.

  • except: this code is only executed if an exception occured in the try block. The except block is required with a try block, even if it contains only the pass statement.

It may be combined with the else and finally keywords.

  • else: Code in the else block is only executed if no exceptions were raised in the try block.

  • finally: The code in the finally block is always executed, regardless of if a an exception was raised or not.

Narrowing of exception-catching scope

The following examples, taken directly from Python’s standard library,
demonstrate how the scope of the try/except can be conveniently narrowed.
To do this with the statement form of try/except would require a temporary
variable, but it’s far cleaner as an expression.

Lib/ipaddress.py:343:

try:
    ips.append(ip.ip)
except AttributeError:
    ips.append(ip.network_address)

Becomes:

ips.append(ip.ip except AttributeError: ip.network_address)

The expression form is nearly equivalent to this:

try:
    _ = ip.ip
except AttributeError:
    _ = ip.network_address
ips.append(_)

Lib/tempfile.py:130:

try:
    dirlist.append(_os.getcwd())
except (AttributeError, OSError):
    dirlist.append(_os.curdir)

Becomes:

dirlist.append(_os.getcwd() except (AttributeError, OSError): _os.curdir)

Lib/asyncore.py:264:

try:
    status.append('%s:%d' % self.addr)
except TypeError:
    status.append(repr(self.addr))

Becomes:

status.append('%s:%d' % self.addr except TypeError: repr(self.addr))

Перехват исключений в Python

В Python исключения обрабатываются при помощи инструкции .

Критическая операция, которая может вызвать исключение, помещается внутрь блока . А код, при помощи которого это исключение будет обработано, — внутрь блока .

Таким образом, мы можем выбрать набор операций, который мы хотим совершить при перехвате исключения. Вот простой пример.

# Для получения типа исключения импортируем модуль sys
import sys

randomList = 

for entry in randomList:
    try:
        print("The entry is", entry)
        r = 1/int(entry)
        break
    except:
        print("Oops!", sys.exc_info(), "occurred.")
        print("Next entry.")
        print()
print("The reciprocal of", entry, "is", r)

Результат:

В данном примере мы, при помощи цикла , производим итерацию списка . Как мы ранее заметили, часть кода, в которой может произойти ошибка, помещена внутри блока .

Если исключений не возникает, блок пропускается, а программа продолжает выполнятся обычным образом (в данном примере так происходит с последним элементом списка). Но если исключение появляется, оно сразу обрабатывается в блоке (в данном примере так происходит с первым и вторым элементом списка).

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

Так как все исключения в Python наследуются из базового класса , мы можем переписать наш код следующим образом:

# Для получения типа исключения импортируем модуль sys
import sys

randomList = 

for entry in randomList:
    try:
        print("The entry is", entry)
        r = 1/int(entry)
        break
    except Exception as e:
        print("Oops!", e.__class__, "occurred.")
        print("Next entry.")
        print()
print("The reciprocal of", entry, "is", r)

Результат выполнения этого кода будет точно таким же.

8.3. Обработка исключений

Существует возможность писать программы, которые обрабатывают выбранные исключения

Посмотрите на следующий пример, который запрашивает у пользователя ввод до тех пор, пока он не введет допустимое целое число, но позволяет пользователю прервать программу (с помощью Control-C или того, что поддерживает конкретная операционная система); обратите внимание, что сгенерированное пользователем прерывание возникает как исключение KeyboardInterrupt (docs.python.org/3/library/exceptions.html#KeyboardInterrupt) (клавиатурное прерывание)

Оператор try (docs.python.org/3/reference/compound_stmts.html#try) работает следующим образом.

  • Сначала выполняется блок try (выражение(я) между ключевыми словами try (docs.python.org/3/reference/compound_stmts.html#try) и except (docs.python.org/3/reference/compound_stmts.html#except)).
  • Если исключение не произошло, блок except пропускается и выполнение оператора try закончено.
  • Если во время выполнения содержимого try возникает исключение, выражения ниже пропускаются. Затем, если тип возникшего исключения соответствует имени исключения после ключевого слова except, содержимое except выполняется, и затем выполнение продолжается после всего оператора try.
  • Если происходит исключение, которое не соответствует имени исключения в строке except, оно передается на внешний оператор try; если обработчик не найден, то исключение становится необработанным и выполнение останавливается с сообщением, как показано выше.

Оператор try может иметь более, чем один пункт except, специальные обработчики для различных исключений. Только один обработчик будет выполнен. Обработчики обрабатывают только те исключения, которые происходят в соответствующей им части try, но не в других обработчиках оператора try. В строке except можно перечислить несколько исключений, взяв их в скобки как кортеж, например:

Класс в блоке except совместим с исключением, если он является таким же классом или базовым классом такового (но не наоборот — блок except, перечисляющий производный класс, несовместим с базовым классом). Например, следующий код выведет B, C, D:

Заметьте, что если бы блоки исключений шли в обратном порядке (первым ), то было бы выведено B, B, B, так как сработало бы первое сопоставление блока except.

В последнем пункте except можно опустить название исключения(ий), он будет служить «джокером»

Используйте эту возможность с особой осторожностью, так как таким образом легко замаскировать действительные ошибки программирования! Такой вариант также может быть использован для вывода сообщения об ошибке, и затем повторной генерации исключения (позволяет вызывающему также обработать исключение):. Оператор try ..

except имеет еще опциональную ветку else, которая если присутствует, должны следовать после всех веток except. Это полезно для кода, который должен быть выполнен, если в ветке try не возникло никакого исключения. Например:

Оператор try … except имеет еще опциональную ветку else, которая если присутствует, должны следовать после всех веток except. Это полезно для кода, который должен быть выполнен, если в ветке try не возникло никакого исключения. Например:

Использование ветки else лучше, чем добавление дополнительного кода в try, потому что помогает избежать случайного перехвата исключения, которое не было сгенерировано кодом, находящимся под «защитой» оператора try … except.

При возникновении исключения с ним может быть связанное значение, также называемое аргументом исключения. Наличие и тип аргумента зависят от типа исключения.

В ветке except после имени исключения можно указать переменную. Переменная привязана к экземпляру исключения с аргументами хранящимися в . Для удобства экземпляр исключения определяет __str__() (docs.python.org/3/reference/datamodel.html#object.__str__), так что аргументы можно вывести сразу, без того, чтобы ссылаться на . Также возможно проиллюстрировать (instantiate) исключение прежде, чем сгенерировать его и добавлять какие-либо атрибуты, как пожелаете.

Если у исключения есть аргументы, они выводятся как последняя часть (‘detail’ — подробность) сообщения для необработанных исключений.

Обработчики исключений не только обрабатывают исключения, которые происходят непосредственно в ветке try, но и если они происходят внутри функций, которые вызываются (даже ненапрямую) в try. Например:

Python try with else clause

In some situations, you might want to run a certain block of code if the code block inside ran without any errors. For these cases, you can use the optional keyword with the statement.

Note: Exceptions in the else clause are not handled by the preceding except clauses.

Let’s look at an example:

Output

If we pass an odd number:

Enter a number: 1
Not an even number!

If we pass an even number, the reciprocal is computed and displayed.

Enter a number: 4
0.25

However, if we pass 0, we get as the code block inside is not handled by preceding .

Enter a number: 0
Traceback (most recent call last):
  File "<string>", line 7, in <module>
    reciprocal = 1/num
ZeroDivisionError: division by zero

8.5. Исключения, определяемые пользователем

В программах можно создавать свои собственные исключения, создав новый класс исключения (см. Классы для подробной информации о классах Python). Исключения должны быть обычно получены от класса Exception (docs.python.org/3/library/exceptions.html#Exception), прямо или опосредованно.

Могут быть определены классы исключений, которые делают любое, что делают другие классы, но обычно оставляют простыми, часто только предлагающими ряд атрибутов, которые позволяют информации об ошибке быть извлеченной обработчиками исключения. При создании модуля, который может возбуждать несколько различных ошибок, обычной практикой является создание базового класса для исключений, определенных модулем, и подкласса для создания конкретных классов исключений для различных условий ошибок:

Большинство исключений определяются с именами, которые заканчиваются на «Error», похоже на именование стандартных исключений.

Многие стандартные модули определяют свои собственные исключения для сообщения об ошибках, которые могут возникнуть в функциях, которые в них определены. Более подробная информация о классах представлена в главе Классы.

Python NumPy

NumPy IntroNumPy Getting StartedNumPy Creating ArraysNumPy Array IndexingNumPy Array SlicingNumPy Data TypesNumPy Copy vs ViewNumPy Array ShapeNumPy Array ReshapeNumPy Array IteratingNumPy Array JoinNumPy Array SplitNumPy Array SearchNumPy Array SortNumPy Array FilterNumPy Random
Random Intro
Data Distribution
Random Permutation
Seaborn Module
Normal Distribution
Binomial Distribution
Poisson Distribution
Uniform Distribution
Logistic Distribution
Multinomial Distribution
Exponential Distribution
Chi Square Distribution
Rayleigh Distribution
Pareto Distribution
Zipf Distribution

NumPy ufunc
ufunc Intro
ufunc Create Function
ufunc Simple Arithmetic
ufunc Rounding Decimals
ufunc Logs
ufunc Summations
ufunc Products
ufunc Differences
ufunc Finding LCM
ufunc Finding GCD
ufunc Trigonometric
ufunc Hyperbolic
ufunc Set Operations

Python NumPy

NumPy IntroNumPy Getting StartedNumPy Creating ArraysNumPy Array IndexingNumPy Array SlicingNumPy Data TypesNumPy Copy vs ViewNumPy Array ShapeNumPy Array ReshapeNumPy Array IteratingNumPy Array JoinNumPy Array SplitNumPy Array SearchNumPy Array SortNumPy Array FilterNumPy Random
Random Intro
Data Distribution
Random Permutation
Seaborn Module
Normal Distribution
Binomial Distribution
Poisson Distribution
Uniform Distribution
Logistic Distribution
Multinomial Distribution
Exponential Distribution
Chi Square Distribution
Rayleigh Distribution
Pareto Distribution
Zipf Distribution

NumPy ufunc
ufunc Intro
ufunc Create Function
ufunc Simple Arithmetic
ufunc Rounding Decimals
ufunc Logs
ufunc Summations
ufunc Products
ufunc Differences
ufunc Finding LCM
ufunc Finding GCD
ufunc Trigonometric
ufunc Hyperbolic
ufunc Set Operations

7.1.4. Подходы к обработке ошибок¶

При написании кода необходимо предусматривать, что в определенном месте программы может возникнуть ошибка и дополнять код на случай ее возникновения.

Существует два ключевых подхода программирования реакции на возможные ошибки:

  1. «Семь раз отмерь, один раз отрежь» — LBYL (англ. Look Before You Leap);

  2. «Легче попросить прощения, чем разрешения» — EAFP (англ. «It’s Easier To Ask Forgiveness Than Permission»).

В Листинге 7.1.2 приведен пример сравнения двух подходов.

Листинг 7.1.2 — Псевдокод функций, использующих разные подходы к обработке ошибок: «Семь раз отмерь, один раз отрежь» и «Легче попросить прощения, чем разрешения»

Обе функции возвращают решение линейного уравнения и НИЧЕГО, если 'a' = 


ФУНКЦИЯ найти_корень_1(a, b):
    ЕСЛИ a не равно 
        ВЕРНУТЬ -b  a
    ИНАЧЕ
        ВЕРНУТЬ НИЧЕГО


ФУНКЦИЯ найти_корень_2(a, b):
    ОПАСНЫЙ БЛОК КОДА      # Внутри данного блока пишется код, который
        ВЕРНУТЬ -b  a     # потенциально может привести к ошибкам
    ЕСЛИ ПРОИЗОШЛА ОШИБКА  # В случае деления на 0 попадаем сюда
        ВЕРНУТЬ НИЧЕГО

Подход «Семь раз отмерь, один раз отрежь» имеет определенные минусы:

  • проверки могут уменьшить читаемость и ясность основного кода;

  • код проверки может дублировать значительную часть работы, осуществляемой основным кодом;

  • разработчик может легко допустить ошибку, забыв какую-либо из проверок;

  • ситуация может изменится между моментом проверки и моментом выполнения операции.

Коллекции Python и их временная сложность

Список (list)

Список является одной из самых важных структур данных в Python. Можно использовать списки для создания стека или очереди. Списки — это упорядоченные и изменяемые коллекции, которые можно обновлять по желанию.

Операции списка и их временная сложность

Вставка: O(n).
Получение элемента: O(1).
Удаление элемента: O(n).
Проход: O(n).
Получение длины: O(1).

Множество (set)

Множества также являются одними из наиболее используемых типов данных в Python. Множество представляет собой неупорядоченную коллекцию. Множество не допускает дублирования, и, следовательно, каждый элемент в множестве уникален. Множество поддерживает множество математических операций, таких как объединение, разность, пересечение и так далее.

Операции с множествами и их временная сложность

Проверить наличие элемента в множестве: O(1).
Отличие множества A от B: O(длина A).
Пересечение множеств A и B: O(минимальная длина A или B).
Объединение множеств A и B: O(N) , где N это длина (A) + длина (B).

Словарь (dict)

Словарь — это коллекция пар ключ-значение. Ключи в словаре уникальны, чтобы предотвратить коллизию элементов. Это чрезвычайно полезная структура данных.

Студенческое соревнование по кибербезопасности «Кибервызов: новый уровень»

29–31 августа, онлайн, беcплатно

tproger.ru

События и курсы на tproger.ru

Словари индексируются по ключам, которые могут быть строками, числами или даже кортежами со строками, числами или кортежами. Над словарём можно выполнить ряд операций, таких как сохранение значения для ключа, извлечение элемента на основе ключа, или итерация по элементам и так далее.

Операции со словарями и их временная сложность

Здесь мы считаем, что ключ используется для получения, установки или удаления элемента.

Получение элемента: O(1).
Установка элемента: O(1).
Удаление элемента: O(1).
Проход по словарю: O(n).

Assertions in Python

An assertion is a sanity-check that you can turn on or turn off when you are done with your testing of the program.

  • The easiest way to think of an assertion is to liken it to a raise-if statement (or to be more accurate, a raise-if-not statement). An expression is tested, and if the result comes up false, an exception is raised.

  • Assertions are carried out by the assert statement, the newest keyword to Python, introduced in version 1.5.

  • Programmers often place assertions at the start of a function to check for valid input, and after a function call to check for valid output.

The assert Statement

When it encounters an assert statement, Python evaluates the accompanying expression, which is hopefully true. If the expression is false, Python raises an AssertionError exception.

The syntax for assert is −

assert Expression

If the assertion fails, Python uses ArgumentExpression as the argument for the AssertionError. AssertionError exceptions can be caught and handled like any other exception, using the try-except statement. If they are not handled, they will terminate the program and produce a traceback.

Example

Here is a function that converts a given temperature from degrees Kelvin to degrees Fahrenheit. Since 0° K is as cold as it gets, the function bails out if it sees a negative temperature −

#!/usr/bin/python3

def KelvinToFahrenheit(Temperature):
   assert (Temperature >= 0),"Colder than absolute zero!"
   return ((Temperature-273)*1.8)+32

print (KelvinToFahrenheit(273))
print (int(KelvinToFahrenheit(505.78)))
print (KelvinToFahrenheit(-5))

When the above code is executed, it produces the following result −

32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print KelvinToFahrenheit(-5)
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!

Handling an exception

If you have some suspicious code that may raise an exception, you can defend your program by placing the suspicious code in a try: block. After the try: block, include an except: statement, followed by a block of code which handles the problem as elegantly as possible.

Syntax

Here is simple syntax of try….except…else blocks −

try:
   You do your operations here;
   ......................
except ExceptionI:
   If there is ExceptionI, then execute this block.
except ExceptionII:
   If there is ExceptionII, then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

Here are few important points about the above-mentioned syntax −

  • A single try statement can have multiple except statements. This is useful when the try block contains statements that may throw different types of exceptions.

  • You can also provide a generic except clause, which handles any exception.

  • After the except clause(s), you can include an else-clause. The code in the else-block executes if the code in the try: block does not raise an exception.

  • The else-block is a good place for code that does not need the try: block’s protection.

Example

This example opens a file, writes content in the, file and comes out gracefully because there is no problem at all −

#!/usr/bin/python

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print "Error: can\'t find file or read data"
else:
   print "Written content in the file successfully"
   fh.close()

This produces the following result −

Written content in the file successfully

Example

This example tries to open a file where you do not have write permission, so it raises an exception −

#!/usr/bin/python

try:
   fh = open("testfile", "r")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print "Error: can\'t find file or read data"
else:
   print "Written content in the file successfully"

This produces the following result −

Error: can't find file or read data
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *