Обработка исключений в Python: подробное руководство
Введение
Python предоставляет две важные функции для обработки неожиданных ошибок и добавления возможностей отладки:
Обработка исключений (Exception Handling) — рассматривается в этом руководстве.
Утверждения (Assertions) — рассматриваются в отдельном разделе.
Стандартные исключения Python
| № | Исключение и описание |
|---|---|
| 1 | Exception — базовый класс для всех исключений. |
| 2 | StopIteration — возникает, когда метод next() итератора не указывает на объект. |
| 3 | SystemExit — возникает функцией sys.exit(). |
| 4 | StandardError — базовый класс для всех встроенных исключений, кроме StopIteration и SystemExit. |
| 5 | ArithmeticError — базовый класс для ошибок числовых вычислений. |
| 6 | OverflowError — вычисление превышает максимальный лимит числового типа. |
| 7 | FloatingPointError — ошибка вычисления с плавающей точкой. |
| 8 | ZeroDivisionError — деление или модуль на ноль для всех числовых типов. |
| 9 | AssertionError — неудача оператора assert. |
| 10 | AttributeError — неудача ссылки на атрибут или присваивания. |
| 11 | EOFError — нет ввода от raw_input() или input() и достигнут конец файла. |
| 12 | ImportError — неудача оператора import. |
| 13 | KeyboardInterrupt — пользователь прервал выполнение (обычно Ctrl+C). |
| 14 | LookupError — базовый класс для ошибок поиска. |
| 15 | IndexError — индекс не найден в последовательности. |
| 16 | KeyError — указанный ключ не найден в словаре. |
| 17 | NameError — идентификатор не найден в локальном или глобальном пространстве имен. |
| 18 | UnboundLocalError — попытка доступа к локальной переменной в функции, но значение не назначено. |
| 19 | EnvironmentError — базовый класс для исключений, возникающих вне среды Python. |
| 20 | IOError — неудача операции ввода/вывода (например, print или open() для несуществующего файла). |
| 21 | OSError — ошибки, связанные с операционной системой. |
| 22 | SyntaxError — ошибка в синтаксисе Python. |
| 23 | IndentationError — неправильно указан отступ. |
| 24 | SystemError — интерпретатор обнаружил внутреннюю проблему, но не завершает работу. |
| 25 | SystemExit — интерпретатор Python завершен через sys.exit(). Если не обработано, вызывает выход. |
| 26 | TypeError — операция или функция недопустима для указанного типа данных. |
| 27 | ValueError — встроенная функция имеет правильный тип аргументов, но недопустимые значения. |
| 28 | RuntimeError — сгенерированная ошибка не вписывается ни в одну категорию. |
| 29 | NotImplementedError — абстрактный метод, требующий реализации в наследнике, не реализован. |
Утверждения (Assertions) в Python
Утверждение — это проверка здравого смысла, которую можно включить или выключить после завершения тестирования программы.
Проще всего представить утверждение как оператор raise-if (точнее, raise-if-not). Выражение проверяется, и если результат ложен, возбуждается исключение.
Утверждения выполняются оператором assert, ключевым словом, добавленным в версии 1.5.
Программисты часто помещают утверждения в начало функции для проверки валидности входных данных, и после вызова функции — для проверки валидности выходных данных.
Оператор assert
При обнаружении оператора assert Python оценивает сопровождающее выражение, которое ожидается истинным. Если выражение ложно, Python возбуждает исключение AssertionError.
Синтаксис:
assert Expression[, Arguments]
Если утверждение не проходит, Python использует Arguments как аргумент для AssertionError. Исключения AssertionError можно перехватывать и обрабатывать как любые другие с помощью try-except, но если не обработаны, они завершают программу и выдают трассировку.
Пример
Функция конвертирует температуру из Кельвинов в Фаренгейты. Нуль Кельвинов — это абсолютный ноль, поэтому функция прерывается при отрицательной температуре:
#!/usr/bin/python
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))
Результат:
32.0
451
Traceback (most recent call last):
File "test.py", line 9, in
print(KelvinToFahrenheit(-5))
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0), "Colder than absolute zero!"
AssertionError: Colder than absolute zero!
Что такое исключение?
Исключение — это событие, происходящее во время выполнения программы, которое нарушает нормальный поток инструкций. В общем, когда скрипт Python сталкивается с ситуацией, с которой не может справиться, он возбуждает исключение. Исключение — это объект Python, представляющий ошибку.
Когда скрипт возбуждает исключение, он должен либо обработать его немедленно, иначе завершается и выходит.
Обработка исключения
Если у вас есть подозрительный код, который может возбудить исключение, вы можете защитить программу, поместив этот код в блок try:. После блока try: добавьте оператор except:, за которым следует блок кода, обрабатывающий проблему максимально элегантно.
Синтаксис
try:
# Ваши операции
...
except ExceptionI:
# Если возникло ExceptionI, выполнить этот блок
except ExceptionII:
# Если возникло ExceptionII, выполнить этот блок
...
else:
# Если исключений не было, выполнить этот блок
Важные моменты
Один оператор
tryможет иметь несколько операторовexcept. Полезно, когда блокtryсодержит операторы, которые могут выбросить разные типы исключений.Можно предоставить общий
except, который обрабатывает любое исключение.После
exceptможно добавитьelse-блок. Код вelseвыполняется, если вtryне возникло исключений.else-блок — хорошее место для кода, не требующей защитыtry.
Пример 1: успешная запись в файл
#!/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()
Результат:
Written content in the file successfully
Пример 2: ошибка прав доступа
#!/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")
Результат:
Error: can't find file or read data
Блок except без указания исключений
Можно использовать except без указания исключений:
try:
# Операции
...
except:
# При любом исключении выполнить этот блок
...
else:
# Если исключений нет
...
Такой try-except перехватывает все исключения. Это считается плохой практикой, так как не позволяет определить причину проблемы.
Блок except с несколькими исключениями
Можно использовать один except для обработки нескольких исключений:
try:
# Операции
...
except (Exception1[, Exception2[, ... ExceptionN]]):
# Если возникло любое исключение из списка
...
else:
# Если исключений нет
...
Блок try-finally
Можно использовать блок finally: вместе с try:. Блок finally — место для кода, который должен выполниться всегда, независимо от того, возбудило ли исключение блок try или нет.
try:
# Операции
...
# Из-за исключения это может быть пропущено
finally:
# Это всегда будет выполнено
...
Нельзя использовать else вместе с finally.
Пример
#!/usr/bin/python
try:
fh = open("testfile", "w")
fh.write("This is my test file for exception handling!!")
finally:
print("Error: can't find file or read data")
Если нет прав на запись, результат:
Error: can't find file or read data
Чище тот же пример:
#!/usr/bin/python
try:
fh = open("testfile", "w")
try:
fh.write("This is my test file for exception handling!!")
finally:
print("Going to close the file")
fh.close()
except IOError:
print("Error: can't find file or read data")
Когда исключение выбрасывается в блоке try, выполнение сразу переходит в блок finally. После выполнения всех операторов в finally исключение возбуждается снова и обрабатывается в except следующего уровня try-except.
Аргумент исключения
Исключение может иметь аргумент — значение, дающее дополнительную информацию о проблеме. Содержимое аргумента варьируется по исключениям. Перехват аргумента происходит путем указания переменной в предложении except:
try:
# Операции
...
except ExceptionType, Argument:
# Можно вывести значение Argument
...
Для одного исключения переменная может следовать за именем исключения в операторе except. Для нескольких исключений — переменная может следовать за кортежем исключений.
Переменная получает значение исключения, обычно содержащее причину. Может быть одиночным значением или кортежем (строка ошибки, номер ошибки, расположение ошибки).
Пример
#!/usr/bin/python
def temp_convert(var):
try:
return int(var)
except ValueError, Argument:
print("The argument does not contain numbers\n", Argument)
temp_convert("xyz")
Результат:
The argument does not contain numbers
invalid literal for int() with base 10: 'xyz'
Возбуждение исключений (raise)
Можно возбуждать исключения несколькими способами с помощью оператора raise. Общий синтаксис:
raise [Exception [, args [, traceback]]]
Exception — тип исключения (например, NameError), args — значение для аргумента исключения (опционально, по умолчанию None), traceback — объект трассировки (редко используется).
Пример
Исключение может быть строкой, классом или объектом. Большинство исключений ядра Python — классы с аргументом-экземпляром класса. Определение новых исключений просто:
def functionName(level):
if level < 1:
raise "Invalid level!", level
# Код ниже не выполнится, если возбуждено исключение
Примечание: Чтобы перехватить исключение, предложение except должно ссылаться на то же исключение (класс или строку). Для перехвата вышеуказанного:
try:
# Бизнес-логика
except "Invalid level!":
# Обработка исключения
else:
# Остальной код
Пользовательские исключения
Python позволяет создавать свои исключения, наследуя классы от стандартных встроенных исключений.
Пример, связанный с RuntimeError. Создается класс, наследуемый от RuntimeError. Полезно для отображения более конкретной информации при перехвате исключения.
В блоке try возбуждается пользовательское исключение и перехватывается в блоке except. Переменная e создает экземпляр класса Networkerror.
class Networkerror(RuntimeError):
def __init__(self, arg):
self.args = arg
После определения класса можно возбуждать исключение так:
try:
raise Networkerror("Bad hostname")
except Networkerror, e:
print(e.args)
Python
- Освоение типов данных в Python: практическое руководство
- Мастерство операторов Python: Полное руководство
- Оператор pass в Python: практическое руководство
- Аргументы функций в Python: позиционные, именованные и параметры по умолчанию
- Словари в Python: создание, манипуляции и продвинутые техники
- Ошибки и встроенные исключения в Python: полное руководство
- Обработка исключений в Python: try, except, else и finally подробно
- Пользовательские исключения в Python: практическое руководство
- Итераторы в Python: как они работают и как создать свои
- Замыкания в Python: как вложенные функции захватывают переменные