2.25. Обробка помилок¶
Більшість помилок часу виконання в Python виявляються як винятки – іменований, структурований спосіб повідомити, що щось пішло не так. ValueError, TypeError, KeyError, OSError, MemoryError – усі це приклади; кожен є класом, і виклик одного з них зупиняє поточний виклик та шукає обробник у навколишньому коді.
2.25.1. try / except¶
Загорніть блок коду в try, щоб перехопити будь-який виняток, який він може викликати:
try:
n = int(input_text)
except ValueError:
n = 0
Якщо перетворення int(...) не вдасться, керування переходить до блоку except замість подальшого поширення помилки. Якщо input_text містив коректний цілочисельний рядок, блок except пропускається.
Один блок try може мати кілька блоків except, кожен з яких перехоплює інший вид помилки:
try:
value = data[key]
except KeyError:
value = None
except TypeError:
value = -1
Python перевіряє їх по черзі; перший, клас винятку якого підходить, обробляє проблему. Перехоплення Exception (базового класу для майже всього) обробляє будь-яку помилку; резервуйте це для найзовнішнього шару програми, де альтернатива – аварійне завершення.
Попередження
Голий except: (без класу після ключового слова) також перехоплює KeyboardInterrupt – виняток, який IDE надсилає при натисканні кнопки зупинити для переривання запущеного скрипта. Цикл, загорнутий у голий except: pass, поглине переривання та продовжить виконання, не залишивши способу зупинити скрипт, крім перезапуску живлення.
Надавайте перевагу except Exception: перед голим except:, коли вам дійсно потрібно широке перехоплення. KeyboardInterrupt успадковується від BaseException, а не від Exception, тому except Exception: залишає кнопку зупинки робочою.
2.25.1.1. Перегляд винятку¶
Щоб прочитати повідомлення, прикріплене до винятку, назвіть його через as:
try:
f = open("data.txt")
except OSError as e:
print("could not open file:", e)
Змінна, прив’язана через as, дійсна лише всередині блоку except.
2.25.2. else та finally¶
Блок try має два необов’язкові розширення.
else виконується лише тоді, коли try завершився без виклику винятку:
try:
value = compute()
except ValueError:
print("bad input")
else:
print("got", value)
Розміщення «що робити, якщо все пройшло добре» в else звужує блок try – лише рядок, який може не вдатися, належить у try.
finally виконується в кінці в будь-якому випадку – незалежно від того, чи try завершився успішно, чи викликав виняток, який було перехоплено, чи викликав виняток, який поширюється далі:
try:
do_work()
finally:
cleanup()
finally виконується завжди. else виконується лише на шляху без винятку.¶
Для більшості шаблонів «отримати/звільнити» надавайте перевагу контекстному менеджеру перед парою try / finally – ресурс сам керує своїм очищенням.
2.25.3. Поширені вбудовані винятки¶
Короткий перелік винятків, з якими ви будете стикатися часто:
ValueError– правильний тип, неправильне значення (bytes([300])– 300 має правильний тип, але виходить за межі допустимого діапазону байтів 0..255).TypeError– зовсім неправильний тип (len(42)).IndexError– індекс за межами послідовності.AttributeError– звернення до атрибута, якого не існує ("abc".foo).OSError– помилка файлової системи або введення/виведення.MemoryError– вичерпано купу. На середовищі з обмеженою пам’яттю це може відбуватись під час звичайної роботи – не лише в патологічних випадках.