Лутц М. - Изучаем Python (1077325), страница 151
Текст из файла (страница 151)
Они включают тип исключения, а также диагностическую информацию — список строк и функций, которые были активны в момент появления исключения. При работе в интерактивной оболочке файлом является «зЫ(п» (стандартный поток ввода) или «рузЬе)1» (в ИЛЕ), поэтому в данном случае номера строк не несут сколько-нибудь полезной информации. В настоящей программе, запущенной не в интерактивной оболочке, обработчик кроме этого по умолчанию завершает работу программы. Такое действие имеет смысл для простых сценариев — как правило, ошибки в таких сценариях должны быть фатальными и лучшее, что можно сделать при их появлении, — это ознакомиться с текстом сообщения. Но иногда это совсем не то, что нам требуется. Например, серверные программы обычно должны оставаться активными даже после появления внутренних ошибок. Если вам требуется избежать реакции на исключение по умолчанию, достаточно просто перехватить исключение, обернув вызов функции инструкцией г гу: »> 1гу; Гетсоег(х, 4) , ехсер1 1поехЕггог; рг1п1 'роС ехсер11оп' до( ехсер((оп »> Теперь, когда исключение будет возникать при выполнения инструкций в блоке 1 гу, интерпретатор будет автоматически переходить к вашему обработчику (блок под предложением ехсерг, в котором указано имя исключения).
При работе в интерактивной оболочке, как в примере выше, после выполнения блока ехсерг происходит возврат в приглашение к вводу. В настоящих программах инструкции г гу не только перехватывают исключения, но и выполняют действия по восстановле. нию после ошибок: »> Сес се1спег().' 1 гу.' Ге1соег(х, 4) ехсерт 1псехЕггог; рг1пт 'ро1 ехсер11оп' рг1пт 'соп11по1пд' »> се(сепг() рог ехсеР11оп сепг>стор >» На этот раз после того, как исключение было перехвачено и обработано, программа продолжила выполнение ниже всей инструкции 1гув з«З»» 7«0 706 Глава 27. Основы исключений именно поэтому в данном примере было выведено сообщение «соп(йпи1пя». Стандартное сообщение об ошибке не появилось на экране, и программа продолжила работу как ни в чем не бывало, Исключения могут возбуждаться интерпретатором или самой программой, и могут перехватываться или не перехватываться.
Чтобы возбудить исключение вручную, достаточно просто выполнить инструкцию га(зе (или аэвегг, с условным выражением, возвращающим ложь). Исключения, определяемые программой, перехватываются точно так же, как и встроенные исключения: »> Ьеб = 'Ьеб' »> 1гу: ге155 Ьеб ... ехсер1 Ьеб: рг1п1 'рос Ьеб' Во( Ьаб Если исключение, определяемое программой, не перехватывается, оно будет передано обработчику исключений по умолчанию, что приведет к завершению программы с выводом стандартного сообщения об ошибке. В данном случае стандартное сообщение включает текст строки, использовавшейся для идентификации исключения: »> Г5155 Ьеб тгасеьаск (ео51 гесепг са!1 1а51); Е1!Е Г<РУ5ПЕ)1518>", 1>ПЕ 1, 1П > га>55 Ьаб Ьаб В других случаях сообщение об ошибке может включать текст, предоставляемый классами, использованными для идентификации исключений.
Как будет показано в следующей главе, исключения, определяемые в программе, могут определяться в виде строк или классов, но в отличие от строк, исключения на базе классов позволяют сценариям создавать категории исключений, наследовать поведение и добавлять к ним информацию о состоянии. Исключения на базе классов более предпочтительны, чем исключения на базе строк, а кроме того, они станут обязательными в Руьпоп 3.0: »> с1555 Ваб(Ехсер11оп): разе »> бе( бооэеб(): ге15е Веб() »> тгу: бооееб() ехсер1 Веб: рг1пс 'рот Веб' рос Ваб »> 707 Обработка исключений: краткий обзор Наконец, инструкции с гу могут включать блоки 11па11у.
Комбинация С гу/Тспа11у определяет завершающие действия, которые всегда выполняются «на выходе», независимо от того, возникло исключение в блоке С гу или нет: »> сгу; Гетсдег(х, 3) ... Г1па11У: ргспс 'атсег гесоп' агсег гессе Здесь, если блок сгу выполнится без ошибок, будет выполнен блок Тспа11у и программа продолжит свою работу дальше. В этом случае данная инструкция кажется бессмысленной — мы могли бы просто добавить инструкцию ргспс сразу вслед за вызовом функции и вообще убрать инструкцию с гу: ГеСслег(х, 3) рг1пс агсег тесса Однако в таком подходе имеется одна проблема: если в функции возникнет исключение, инструкция рыпс не будет выполнена.
Комбинация с гу/тспа11У позволяет ликвидировать эту проблему — когда в блоке Сгу действительно произойдет исключение, блок Тспа11у будет выполнен, пока программа будет раскручиваться: »> сег агсег().' сгу: Гесспег(х, 4) Г1па11У: ргспС 'естес Татаа' РТ1пт 'аттаг Сгут' »> агсег() агсег тессе Тгасеоаок (аовс гесепс са11 1авс). Е!1е "<всосп>", 11пе 1, сп » Е!1е "<втосп>", 11пе 3, 1п а(Сег Гс1е "<всссп>", 11пе 2, сп Ге!слег 1поехЕггог: втг1по 1поех оыт от галде (1псехеггог выход индекса за пределы строки) Здесь мы не получили сообщение «айег Ссуд», потому что работа программы не была продолжена после блока Сгу/Тспа11у, когда возникло исключение. Вместо этого интерпретатор выполнил действия, предусмотренные блоком г1па11у, после чего исключение достигло предыдущего обработчика (в данном случае — обработчик по умолчанию).
Если изменить вызов внутри функции асс!оп, чтобы он не вызывал исключение, блок Тспа11у все равно будет выполнен, но программа продолжит работу после выхода из инструкции с гу: 7ОВ Глава 27. Основы исключений »> пег агсэг(): тгу: гесспег(х, 3) Г1па11у: рг1пс 'аттег Гесса' рг)пт 'аутег Сгут' »> аутег() аггег гесса аггег ггу> »> на практике комбинацию г гу(ехсерг удобно использовать для перехвата и восстановления после исключений, а комбинацию с гу!11па11у — в случаях, когда необходимо гарантировать выполнение заключительных действий независимо от того, возникло исключение в блоке ггу или нет.
Например, комбинацию с гу/ехсерг можно было бы использовать для перехвата ошибок, возникающих в импортированной библиотеке, созданной сторонним разработчиком, а комбинацию ггу/Г1па11у — чтобы гарантировать закрытие файлов и соединений с сервером. Некоторые из таких практических примеров будут показаны далее в этой книге. Несмотря на то, что эти две комбинации служат двум различным целям, тем не менее, начиная с версии РуФ)гоп 2.5, появилась возможность смешивать предложения ехсерг и 11па11у в одной и той же инструкции сгу — блок Г)па11у будет выполняться всегда, независимо от того, было ли перехвачено исключение предложением ехсерг.
Такое поведение составляет основу исключений — исключения действительно являются очень простым инструментом. Далее в этой части книги мы подробнее поговорим о самих инструкциях, исследуем разные виды предложений, которые могут появляться в инструкции 1г у, и обсудим объекты исключений, основанные на строках и классах. Исключения в языке Ру$поп — это высокоуровневый инструмент управления потоком выполнения. Они могут возбуждаться интерпретатором или самой программой — в любом из этих случаев их можно игнорировать (что вызовет срабатывание обработчика по умолчанию) или перехватывать с помощью инструкций г г у (для обработки в своем программном коде). Инструкция сгу может использоваться в двух логических разновидностях, которые, начиная с версии РуФ)гоп 2.б, могут комбинироваться — одна разновидность выполняет обработку исключений, а другая выполняет завершающий программный код независимо от того, возникло исключение или нет.
Исключения можно возбуждать вручную, с помощью инструкций га1ве и аввегг. А теперь, получив общее представление, рассмотрим подробнее общие формы употребления этих инструкций. Инструкция 1гу/ехсе р1/ейе 709 Инструкция 1гу//ехсерт/е!ее Для начала я представлю 1гу/ехсерс/е1ае и 1гу/г1па11у как разные инструкции, потому что они имеют разное предназначение и не могут комбинироваться в версиях РусЬоп ниже, чем 2.5. Как уже говорилось, начиная с этой версии, ехсер1 и (1па11у могут смешиваться в одной инструкции 1гу — я объясню суть этого изменения после того, как будут исследованы две оригинальные формы по отдельности.
Инструкция сгу — это составная инструкция. Полная ее форма приводится ниже. Она начинается со строки заголовка с ту, вслед за которой располагается блок инструкций (как правило) с отступами, затем следует одно или более предложений ехсерг, которые определяют перехватываемые исключения, и затем следует необязательное предложение е1ае. Слова 1гу, ехсерс и е1ае должны располагаться с одним и тем же отступом (то есть должны быть выровнены по вертикали). Для справки ниже приводится полный формат инструкции: ггу; <втатешепта> № Сначала выполняютоя зги действия ехсерт <пашеп>: <ыатешептв> № запускается, если в блоке тгу возникло исключение паше 1 ехсерс <паше2>, <бата>: <втатешептз> № Запускаетоя е случае исключения пашей № и получает дополнительные денные ехсерт (пашез, павел); <всасешептв> № Запускается, если возникло любое из этик исключений ехсерт: <ыасешептз> № запускаетоя для всех (оотальнык) возникших исключений е1ве: <втатешептз> № Запуокаетоя, если в блоке ггу не возникло исключения В этой инструкции блок под заголовком сгу представляет основное дейслтвие инструкции — программный код, который следует попытаться выполнить.
Предложения ехсерс определяют обрабоюьчики исключений, возникших в ходе выполнения блока 1гу, а предложение е1ве (если присутствует) определяет обработчик для случая отсутствия исключений. Элемент <баса> имеет отношение к особенности инструкций га1зе, которая будет обсуждаться далее в этой главе.
Ниже описывается принцип действия инструкции 1 гу. Когда запускается инструкция 1гу, интерпретатор помечает текущий контекст программы, чтобы вернуться к нему, если возникнет исключение. В первую очередь выполняются инструкции, расположенные под заголовком тгу. Что произойдет дальше, зависит от того, будет ли возбуждено исключение в блоке сгу: Если исключение возникнет во время выполнения инструкций в блоке 1гу, интерпретатор вернется к инструкции сгу и выполнит первое предложение ехсерг, соответствующее возбужденному исключению.
После выполнения блока ехсерг управление будет передано Глава 27. Основы исключений первой инструкции, находящейся за всей инструкцией Сгу (при условии, что в блоке вхсерг не возникло другого исключения). ° Если в блоке с гу возникло исключение, и не было найдено ни одного соответствия среди предложений ехсерс, исключение будет передано инструкции Ггу, стоящей выше в программе, или на верхний уровень процесса (что вынудит интерпретатор аварийно завершить работу программы и вывести сообщение об ошибке по умолчанию). ° Если в процессе выполнения блока сгу не возникло исключение, интерпретатор выполнит инструкции в блоке е1ае (если имеется) и затем выполнение продолжится с первой инструкции, находящейся за всей инструкцией Сгу.
Другими словами, предложения ехсерг перехватывают любые исключения, которые могут возникнуть при выполнении блока сгу, а блок е1ве выполняется только в случае отсутствия исключений в блоке сгу. В предложениях ехсерт находятся обработчики исключений — они перехватывают исключения, которые возникли только в инструкциях блока ггу.