Лутц М. - Изучаем Python (1077325), страница 154
Текст из файла (страница 154)
Разработчики РусЬоп упорно трудятся ыал тем, чтобы избежать подобного развития событий, проверяя все возможные ошибки во время работы. Полное обрушение программы вместе с интерпретатором часто происходит нз-за ошибок в расширениях, написанных на языке С, которые выполняются не пол управлением Руслоп. 719 Объединенная инструкция тгу/ехсерт/йпару возможность смешивать предложения бопа11у, ехсер! и е1ве в одной и той же инструкции. То есть теперь мы можем написать инструкцию, имеющую следующий вид: тгу: основное действие ехсерт Ехсертгопн обработчик! ехсерт Ехсерт1оп2: обрвботчик2 е!ве блок е!ве тгпа1!у' блок Г!пвыу Первым, как обычно, выполняется программный код в блоке основное действие.
Если при выполнении этого блока возбуждается исключение, выполняется проверка всех блоков ехсерт, одного за другим, в поисках блока, соответствующего возникшему исключению. Если было возбуждено исключение Ехсерт1оп1, будет выполнен блок обработчик!, исключение Ехсерттоп2 приведет к запуску обрвботчика2 и т. д. Если исключение не было возбуждено, будет выполнен блок е1ве. Независимо от того, что происходило раньше, блок Гтпа11у будет выполнен только после выполнения основных действий, и после обработки любых возникших исключений. В действительности, блок у!па!1у будет выполнен, даже если исключение возникнет в самом обработчике исключения или в блоке е1ве.
Как всегда, предложение !1па11у не прекращает распространение исключения — если к моменту выполнения блока б!па11у имеется активное исключение, оно продолжает свое распространение после выполнения блока б!гга11у и управление передается куда-то в другое место программы (другой инструкции сгу или обработчику по умолчанию). Если к моменту, когда блок б! па11у будет выполнен, нет активного исключения, выполнение программы продолжится сразу же вслед за инструкцией !ту. Таким образом, блок ттпа11у выполняется всегда, когда: ° В блоке основного действия возникло исключение и было обработано. ° В блоке основного действия возникло исключение и не было обработано.
° В блоке основного действия не возникло исключение. ° В одном из обработчиков возникло новое исключение. Напомню еще раз, предложение ттпа!1у служит, чтобы организовать выполнение завершающих действий, которые должны выполняться всегда при выходе из инструкции т ту, независимо от того, было ли возбуждено исключение и было ли оно обработано. 720 Глава 27, Основы исключений Объединение 6паПу и ехсер1 вложением До появления версии РуС]соп 2.5 существовала возможность объединять предложения с!па!!у и ехсерс в инструкции сгу за счет вложения инструкции Сгу/ехсерС в блок С ту инструкции С ту/!!па!1у (более полно этот прием будет рассматриваться в главе 29). В действительности фрагмент ниже имеет тот же эффект, что и новая форма инструкции, представленная в предыдущем разделе: сгу сгу. основное действие ехсерс Ехсерссоп1: обработчик! ехсерС Ехсерг!оп2: обработчик2 е1ве: нет ошибок Гспа11у: вавершаююие действия Здесь также блок Е ! па!!у всегда выполняется при выходе из инструкции С ту независимо от того, что произошло в блоке основного действия, и независимо от того, выполнялись ли обработчики исключений во вложенной инструкции с ту (представьте, как в этом случае будут развиватьса четыре варианта событий, перечисленные выше, и вы увидите, что все будет выполняться точно так же).
Однако этот эквивалент выглядит менее понятным, чем новая, объединенная форма инструкции. Смешанная форма инструкции проще в написании и выглядит понятнее, поэтому такая форма записи считается в настоящее время предпочтительной. Пример использования объединенной инструкции тгу Ниже приводится пример использования объединенной формы инструкции с ту. Здесь представлены четыре типичных варианта с инструкциями ргспС, описывающими значение каждого из ннх: ргшС '- ° 30.
'ХпЕХСЕРТ1ОН ЯА1БЕО АНО САООНТ' сгу: х = 'враш'[99] ехсерС 1псехЕггог: ргспс 'ехсерс гоп' Гспа11у. ргспС т!па11у гоп' ргспс ассег гоп ргспС '-' * 30, 'ХпНО ЕХСЕРТ10Н ОА1ЯЕО' сгу; х = 'враш'[3] ехсерС 1псехЕггог. рг1пС 'ехсерС гпп' Объединенная инструкция тгу/ехсерт/йпаНу 721 Гтпа11у. ргтпт 'т!па1!у гоп' ргтпт 'аттег гоп' ргтпт '-' * 30, 'ХпйО ЕХСЕРТ!ОИ НА1ЗЕО, ЕЕЗЕ ВОИ' тгу: х = 'враз'[3] ехсерт 1псехЕггог: ргтпт 'ехсерт гоп' е1ве; рг1пт 'е1ве гоп' Гтпа11у: рг!пг 'Г1па11у гчп' рг1пт 'аттег гчп' ргтпт '-' * 30, 'ХпЕХСЕРТ!ОИ ВАТЗЕО ВОТ ИОТ САОВНТ' тгу' х = 1 / 0 ехсерт 1псехЕггог: рг1пт 'ехсерт гчп' ттпа11у рг1пт 'т!па11у гчп' ргпп 'аттег гчп' После запуска этот пример выводит на экран следующий ниже текст.
Исследуйте программный код, чтобы понять, как работает каждый из вариантов: ЕХСЕРТТОМ ВА1ЗЕО АМО СА06НТ ЕхСЕрт гоп т!па11у гоп агтег гчп ИО ЕХСЕРТ!ОИ ВА1ЗЕО ттпа11у гцп аттег гоп МО ЕХСЕРТ!ОМ ВА1ЗЕО, ЕЕЗЕ ВОМ е1ве гоп Ттпа11у гоп агтег гоп ЕХСЕРТ10М ВЯ1ЗЕО ВОТ МОТ СА06НТ 11па11у гоп ТгасеЬаск (юовт гесепт са11 1авт); РТ1е "С:/Рутпоп25/еегдесехс.ру", 11пе 32, 1п <юосц1е> х = 1 / 0 ЕегаОтч!в1опЕггог; тптедег Отч1юоп ог юосо1а Ьу лего (ЕегоО!ч!в!опЕггог: целочисленное деление или деление по модулю на ноль) Этот пример для возбуждения исключений в основном действии использует встроенные операции и полагается на тот факт, что интер- 722 Глава 27. Основы исключений претатор всегда определяет появление ошибок во время выполнения программного кода. В следующем разделе будет показано, как возбуж- дать исключения вручную.
Инструкция гаЬе Чтобы явно возбудить исключение, можно использовать инструкцию га1ае. В общем виде она имеет очень простую форму записи — инструкция га1зе состоит из слова га(ае, за которым могут следовать имя возбуждаемого исключения и дополнительный элемент данных, передаваемый вместе с исключением: В Возбуждает исключение В ПеРедает дополнительнме данине длл обработчика В Повторно возбуждает самое последнее исключение га!ае <паше> гале <паше>, <бата> гале Пример: возбуждение и обработка собственных исключений Программы на языке Русггоп с помощью инструкции га!зе могут возбуждать как встроенные, так и собственные исключения. В настоящее время собственные исключения в программе должны быть представлены объектами экземпляров классов, как, например, йуВаб в следующем примере: Вторая форма позволяет передавать дополнительные данные вместе с исключением, чтобы сообщить обработчику о некоторых подробностях.
Данные, указанные после имени исключения в инструкции гатае, передаются обратно в инструкцию !ту в виде переменной. Если инструкция ! ту включает предложение ехсерг паше, Х:, то дополнительный элемент данных, указанный в инструкции га!ве, будет присвоен переменной Х. Третья форма инструкции га!ве просто повторно возбуждает текущее исключение — это удобно, когда возникает необходимость передать перехваченное исключение другому обработчику. А что используется в качестве имени исключения2 Это может быть имя встроенного исключения из встроенной области видимости (например, 1пбехВггог) или имя любого строкового объекта в программе.
Это может быть также ссылка на класс или экземпляр класса — данная возможность позволяет еще больше обобщить формат инструкции га(ае. Я не буду касаться подробностей такого обобщения, пока мы не приступим к изучению классов исключений в следующей главе Независимо от того, какие исключения будут использованы, они всегда идентифицируются обычными объектами и только одно исключение может быть активным в каждый конкретный момент времени. Как только исключение перехватывается предложением ехсерс, находящимся в любом месте программы, исключение деактивируется (то есть оно не будет передано другой инструкции сгу), если не будет повторно возбуждено при помощи инструкции га!вс или в результате ошибки. угз Инструкция га)ве с1авв МуВас: рава Оег в(от((): га(ве Муааб() тгу: этот(() ехсерт муВао.
рыпт 'рот тт' № Возбудить исключение вручную № Возбуадает исключение № Здесь виполняется обработка исключения № С этого иеста продоляаетсл виполнение програиии На этот раз исключение происходит внутри функции, но в действительности зто не имеет никакого значения — управление немедленно передается блоку ехсерт. Обратите внимание, что инструкция тгу перехватывает собственные исключения программы точно так же, как и встроенные исключения. Пример: передача дополнительных данных инструкции га! бе Как утверждалось выше, инструкция га1ве может передавать дополнительные данные в месте с исключением для использования в обработчике.
Дополнительные данные позволяют передавать обработчику контекстную информацию об исключении. Например, если вы пишете программу анализа содержимого файла, то в случае нахождения ошибки можно было бы возбуждать исключение синтаксической ошибки и вместе с этим исключением передавать обработчику объект, включающий в себя строку и информацию о файле (такой пример будет рассматриваться в главе 28). № Строковий обьект юуЕхсерттоп = 'еггог' оег гатвегт(). гагве юуЕхсерттоп, "пе11о" № Возбудит~ исключение, передать двнние Оег гатвег2() Это бывает полезно, потому что после того, как исключение будет возбуждено, оно может быть перехвачено в другом модуле, то есть инструкция га!ве, возбудившая исключение, и инструкция тгу, перехватившая его, могут находиться в совершенно разных файлах. Поэтому вообще может оказаться невозможным использовать глобальные переменные для сохранения дополнительной информации об исключении, потому что инструкция тгу может даже не знать, в каком модуле находятся эти переменные.