Python на Symbian S60: типы ошибок и способы перехвата

Жуки и другие насекомые...

Программирование — сложный процесс, и вполне естественно, что иногда программист допускает ошибку. Процесс поиска и устранения ошибок в англоязычной литературе принято обозначать термином debugging, мы же будем называть его отладкой.

Существуют три типа ошибок программирования:

1. синтаксические ошибки (syntax errors),

2. ошибки выполнения (runtime errors),

3. семантические ошибки (semantic errors).

Чтобы находить и исправлять ошибки быстрее, имеет смысл научиться их различать.

Синтаксические ошибки (syntax errors)

Любой интерпретатор сможет выполнить программу только в том случае, если программа синтаксически правильна. Когда интерпретатор находит инструкцию, которую не может понять, он прерывает работу и выводит сообщение об ошибке. Даже незначительная опечатка означает, что программа не выполнится:

>>> print print "Hello world"

File "", line 1

                   print print "Hello world"

                               ^

SyntaxError: invalid syntax

>>>

Нелепая ошибка.

 

На этом примере мы два раза в интерактивной консоли ввели оператор print. Ответ интерпретатора таков:

— File ""

имя файла, в котором находится ошибка, ставится в кавычки. В данном случае значение console говорит, что код программы набран прямо в консоли;

— line 1

номер строки с ошибкой;

— print print "Hello world"

^

— SyntaxError: invalid syntax

Указывается тип ошибки. В данном случае — синтаксический.

Ошибки выполнения (runtime errors)

Второй тип ошибок обычно возникает во время выполнения программы (их принято называть исключительными ситуациями, или, коротко, исключениями, по-английски exceptions). Такие ошибки имеют другую причину. Если в программе возникает исключение, то это означает, что случилось непредвиденное: например, программе передали некорректное значение или программа попыталась разделить какое-то значение на ноль, что недопустимо с точки зрения математики. Если операционная система присылает запрос на немедленное завершение программы, то также возникает исключение. Но в простых программах это достаточно редкое явление, поэтому, возможно, с ним вы столкнетесь не сразу:

>>> 1/0

File "", line 1, in ?

ZeroDivisionError, integer division or modulo by zero

>>>

Сообщается об ошибке деления на ноль.

Делить на ноль нельзя!

 

 

Семантические ошибки (semantic errors)

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

Перехват диверсанта

К счастью, Python предоставляет инструкции, с помощью которых можно задать перехват нежелательных действий:

try:

                   <код, при выполнении которого могут появиться исключения>

except <тип исключения, которое необходимо перехватить>:

                   <код, выполняемый после перехвата исключения>

Расшифровка:

— подозрительный код вносится в ветвь try. Этот код и выполняется первым делом;

— ветвь except выполняется в том случае, если код ветви try привел к ошибкам, тому же делению на ноль, к примеру;

— если во время выполнения ветви try генерируется исключение (происходит ошибка), оставшаяся часть ветви пропускается.

— если исключение не соответствует указанному после except, то оно считается не перехваченным. Если для ветви except не указан тип ошибки, то перехватываются все исключения.

>>> def division(a,b):

... try:

... print a/b

... except:

... print "Error"

...

>>> division(6,2)

3

>>> division(2,0)

Error

>>>

Разумный контроль — ключ к успеху!

 

Если нужно перехватить несколько типов исключений, то указывается их кортеж: except (RuntimeError, TypeError, NameError). Какие конкретно бывают ошибки в Python, будет сказано чуть ниже.

После всех ветвей except можно указать необязательную ветвь else, которая будет выполняться в том случае, если во время выполнения ветви try исключений не происходит:

>>> def division(a,b):

... try:

... print a/b

... except ZeroDivisionError:

... print "ZeroDivisionError"

... except (TypeError,NameError):

... print "OtherError"

... else:

... print "No Error"

...

Лучше мы запутаем ошибку, чем она запутает нас!

Обычно лучше использовать ветвь else, чем добавлять код в ветвь try. Это позволит избежать обработки исключений, сгенерированных кодом, который вы и не собирались защищать.

Также инструкция try может иметь «страховочную» ветвь finally, которая выполняется при любых условиях:

>>> def division(a,b):

... try:

... print a/b

... finally:

... print "Goodbye!"

...

Ветвь finally выполняется независимо от того, возникла исключительная ситуация во время выполнения ветви try или нет. Инструкция try может иметь либо ветви except, либо только одну ветвь finally, но не оба варианта сразу.

Данная выше информация очень важна, и, судим по собственному опыту, большинство начинающих уделяют ей мало внимания, затрачивая большое количество времени на поиск ошибок. А ведь грамотное использование этой возможности позволит писать достаточно «умные» программы, которые не закрываются после глупых шагов пользователей (ввод строки вместо числа, например) и непредвиденных обстоятельств (отсутствует нужный файл, например), да к тому же могут проинформировать об ошибке в удобном виде.

Знай врага в лицо!

Как говорит программерская мудрость — старый «баг» лучше новых двух. Чтобы не допускать размножения ошибок, надо знать их в лицо:

ImportError

Ошибка при импорте модуля (скорее всего, неправильно указано его имя):

>>> import appuifwww

Traceback (most recent call last):

File "", line 1, in ?

ImportError: No module named appuifwww

>>>

IndexError

Ошибка, которая генерируется, когда осуществляется попытка обратиться к списку (строке, кортежу) по индексу, превышающему его длину:

>>> list = [1, 2, 3]

>>> list [9]

Traceback (most recent call last):

File "", line 1, in ?

IndexError: list index out of range

>>>

MemoryError

Ошибка из-за нехватки оперативной памяти (например, когда вы пытаетесь создать очень большой список функцией range):

>>> range (10000000)

Traceback (most recent call last):

File "", line 1, in ?

MemoryError

>>>

NameError

Ошибка имени (используется несуществующая переменная):

>>> 1 + a

Traceback (most recent call last):

File "", line 1, in ?

NameError: name 'c' is not defined

>>>

SyntaxError

Синтаксическая ошибка (будьте внимательны!):

>>> 1 + 0 +

File "", line 1

1+0+

^

SyntaxError: invalid syntax

>>>

TypeError

Ошибка генерируется, когда осуществляется попытка применить операцию к объекту не того типа (например, складывать число и строку):

>>> 1 + ‘2’

Traceback (most recent call last):

File "", line 1, in ?

TypeError: unsupported operand types for +: 'int' and 'str'

>>>

ZeroDivisionError

Ошибка деления на ноль:

>>> 1 / 0

Traceback (most recent call last):

File "", line 1, in ?

ZeroDivisionError: integer division or modulo by zero

>>>

В следующей статье мы займемся изучением способов создания интерфейса для своей программы (причем на русском языке) и попутно разберем понятие объект в языке Python.






Рекомендуемый контент




Copyright © 2010-2017 housea.ru. Контакты: info@housea.ru При использовании материалов веб-сайта Домашнее Радио, гиперссылка на источник обязательна.