Автостопом по Python | страница 38



Ошибки никогда не должны замалчиваться/Если не замалчиваются явно

Обработка ошибок в Python выполняется с помощью выражения try. Пример из пакета HowDoI (более подробно описывается в разделе «HowDoI» в главе 5) Бена Глейтсмана (Ben Gleitzman) показывает, когда замалчивать ошибки приемлемо:

>def format_output(code, args):

>····if not args['color']:

>········return code

>····lexer = None

>····# попробуем отыскать лексеры с помощью тегов Stack Overflow

>····# или аргументов query

>····for keyword in args['query'].split() + args['tags']:

>········try:

>············lexer = get_lexer_by_name(keyword)

>············break

>········except ClassNotFound:

>············pass

>····# лексер не найден, пробуем угадать

>····if not lexer:

>········lexer = guess_lexer(code)

>····return highlight(code,

>····················lexer,

>····················TerminalFormatter(bg='dark'))

Перед вами часть пакета, который предоставляет сценарий командной строки, позволяющий найти в Интернете (по умолчанию на сайте Stack Overflow) способ выполнить задачу по программированию. Функция format_output() подсвечивает синтаксис, просматривая теги вопроса на предмет строки, которую смог разобрать лексер (также он называется токенайзером; теги python, java или bash позволят определить лексер, который нужно использовать для разбиения и подсвечивания кода), а затем, если он даст сбой, пробует определить язык по самому коду. Когда программа достигает оператора try, она может пойти по одному из трех путей:

• поток выполнения входит в блок try (весь код, расположенный между try и except), лексер успешно определяется, цикл прерывается, и функция возвращает код, подсвеченный с помощью выбранного лексера;

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

• генерируется какое-то другое исключение (например, KeyboardInterrupt), которое не обрабатывается и поднимается на верхний уровень, останавливая выполнение.

Часть афоризма «не замалчиваются» препятствует чрезмерному выявлению ошибок. Рассмотрим пример (можете попробовать запустить его в отдельном окне консоли — так будет проще прервать выполнение, когда вы во все вникнете):

>>>> while True:

>… ····try:

>… ········print("nyah", end=" ")

>… ····except:

>… ········pass

Или не пробуйте запускать его. Поскольку для блока except не указано конкретное исключение, он будет отлавливать все исключения, в том числе KeyboardInterrupt (Ctrl+C в консоли POSIX), и игнорировать их. Соответственно, он проигнорирует множество ваших попыток прервать его работу. Это не просто проблема с прерываниями — блок except также может скрывать ошибки, что вызовет проблемы в будущем (их станет трудно диагностировать). Поэтому