Винятки в Python. Конструкція try … except для оброобки винятків

Винятки в Python. Конструкція try … except для оброобки винятків#

Винятки (exceptions) — ще один тип даних в Python. Винятки необхідні для того, щоб повідомляти програмісту про помилки. Найпростіший приклад винятку — поділ на нуль:

100/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_22196/621970991.py in <module>
----> 1 100/0

ZeroDivisionError: division by zero

У цьому прикладі інтерпретатор повідомляє про те, що він впіймав виняток і надрукував інформацію (Traceback (most recent call last)). Далі ім’я файлу (~\AppData\Local\Temp/ipykernel_22196/621970991.py in <module>). Ім’я дивне, тому що програма виконується в інтерактивному режимі, рядок в файлі (line 1); Вираз, в якому сталася помилка (100/0). Назва винятку (ZeroDivisionError) і короткий опис винятку (division by zero).

Зрозуміло, можливі й інші винятки:

2+'1'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_22196/3484758724.py in <module>
----> 1 2+'1'

TypeError: unsupported operand type(s) for +: 'int' and 'str'
int('qwerty')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_22196/937401132.py in <module>
----> 1 int('qwerty')

ValueError: invalid literal for int() with base 10: 'qwerty'

У цих двох прикладах генеруються винятки TypeError і ValueError відповідно. Підказки дають повну інформацію про те, де породжений виняток, і з чим це пов’язано.

Ієрархія вбудованих в Python винятків#

BaseException — базовий виняток, від якого беруть початок всі інші.

SystemExit — виняток, що породжується функцією sys.exit при виході з програми.

KeyboardInterrupt — породжується при перериванні програми користувачем (зазвичай сполучення клавіш Ctrl+C).

GeneratorExit — породжується при виклику методу close об’єкту generator.

Exception — а ось тут вже закінчуються повністю системні виключення (які краще не чіпати) і починаються звичайні, з якими можна працювати.

StopIteration — породжується вбудованою функцією next, якщо в ітераторі більше немає елементів.

ArithmeticError — арифметична помилка.

  • FloatingPointError — породжується при невдалому виконанні операції з плаваючою комою. На практиці зустрічається нечасто.

  • OverflowError — виникає, коли результат арифметичної операції занадто великий для представлення. Не з’являється при звичайній роботі з цілими числами (так як Python підтримує довгі числа), але може виникати в деяких інших.

  • ZeroDivisionError — ділення на нуль.

AssertionError — вираз у функції assert помилковий.

AttributeError — об’єкт не має даного атрибута (значення або методу).

BufferError — операція, пов’язана з буфером, не може бути виконана.

EOFError — функція натрапила на кінець файлу і не змогла прочитати те, що хотіла.

ImportError — не вдалося імпортування модуля або його атрибута.

LookupError — некоректний індекс або ключ.

IndexError — індекс не входить в діапазон елементів.

KeyError — неіснуючий ключ (в словнику, множині або іншому об’єкті).

MemoryError — недостатньо пам’яті.

NameError — не знайдено змінної з таким ім’ям.

UnboundLocalError — зроблено посилання на локальну змінну у функції, але змінна не визначена раніше.

OSError — помилка, пов’язана з системою.

  • BlockingIOError

ChildProcessError — невдача при операції з дочірнім процесом.

ConnectionError — базовий клас для винятків, пов’язаних з підключеннями.

  • BrokenPipeError

  • ConnectionAbortedError

  • ConnectionRefusedError

  • ConnectionResetError

FileExistsError — спроба створення файлу або директорії, яка вже існує.

FileNotFoundError — файл або директорія не існує.

InterruptedError — системний виклик перерваний вхідним сигналом.

IsADirectoryError — очікувався файл, але це директорія.

NotADirectoryError — очікувалася директорія, але це файл.

PermissionError — не вистачає прав доступу.

ProcessLookupError — вказаного процесу не існує.

TimeoutError — закінчився час очікування.

ReferenceError — спроба доступу до атрибуту зі слабким посиланням.

RuntimeError — виникає, коли виняток не попадає ні під одну з інших категорій.

NotImplementedError — виникає, коли абстрактні методи класу вимагають перевизначення в дочірніх класах.

SyntaxError — синтаксична помилка.

IndentationError — неправильні відступи.

TabError — змішування у відступах табуляції і пробілів.

SystemError — внутрішня помилка.

TypeError — операція застосована до об’єкту невідповідного типу.

ValueError — функція отримує аргумент правильного типу, але некоректного значення.

UnicodeError — помилка, пов’язана з кодуванням / розкодуванням Unicode в рядках.

UnicodeEncodeError — виняток, пов’язаний з кодуванням Unicode.

UnicodeDecodeError — виняток, пов’язаний з декодуванням Unicode.

UnicodeTranslateError — виняток, пов’язаний з перекладом Unicode.

Warning — попередження.

Тепер, знаючи, коли і за яких обставин можуть виникнути виключення, можна їх обробляти. Для обробки виключень використовується конструкція try ... except. Перший приклад застосування цієї конструкції:

try:
    k = 1 / 0
except ZeroDivisionError:
    k = 0
print(k)
0

У блоці try виконується інструкція, яка може породити виняток, а у блоці except — перехоплюється. При цьому перехоплюються як саме виняток, так і його нащадки. Наприклад, перехоплюючи ArithmeticError, також перехоплюються FloatingPointError, OverflowError і ZeroDivisionError.

try:
    k = 1 / 0
except ArithmeticError:
    k = 0
print(k)
0

Також можлива інструкція except без аргументів, яка перехоплює взагалі все (і переривання з клавіатури, і системний вихід і т. д.). Тому у такій формі інструкція except практично не використовується, а використовується except Exception. Однак найчастіше перехоплюють виключення по одному, для спрощення налагодження (раптом буде здійснена помилка, а except її перехопить).

Ще дві інструкції — це finally і else. finally виконує блок інструкцій у будь-якому випадку, чи було виключення, чи ні (застосовні, коли потрібно неодмінно щось зробити, наприклад, закрити файл). Інструкція else виконується у тому випадку, якщо виключення не було.

f = open('1.txt')
ints = []
try:
    for line in f:
        ints.append(int(line))
except ValueError:
    print('Це не число. Виходимо')
except Exception:
    print('Це що ще таке?' )
else:
    print('Все добре.')
finally:
    f.close()
    print('Я закрив файл.')
#Саме у такому порядку: try, група except, потім else, і тільки потім finally.