При разработке программного обеспечения могут возникать различные типы ошибок. Это могут быть синтаксические ошибки, логические ошибки или ошибки времени выполнения.
Синтаксические ошибки, скорее всего, возникают на начальном этапе разработки и являются результатом неправильного синтаксиса. Синтаксические ошибки могут быть легко обнаружены при компиляции программы для выполнения.
Логические ошибки, с другой стороны, являются результатом неправильной логической реализации. Примером может служить программа, обращающаяся к несортированному списку в предположении, что он отсортирован. Логические ошибки являются наиболее сложными для отслеживания.
Ошибки во время выполнения — самые интересные ошибки, которые возникают, если мы не рассматриваем все угловые случаи. Примером будет попытка получить доступ к несуществующему файлу.
В этом руководстве мы узнаем, как обрабатывать ошибки в Python и как регистрировать ошибки, чтобы лучше понять, что пошло не так внутри приложения.
Обработка исключений в Python
Давайте начнем с простой программы для добавления двух чисел в Python. Наша программа принимает в качестве входных данных два параметра и выводит сумму. Вот программа на Python для добавления двух чисел:
1
2
3
4
|
def addNumbers(a, b):
print a + b
addNumbers(5, 10)
|
Попробуйте запустить вышеуказанную программу на Python, и вы должны напечатать сумму.
1
|
15
|
При написании вышеупомянутой программы мы не учитывали тот факт, что что-то может пойти не так. Что если один из переданных параметров не является числом?
1
|
addNumbers(», 10)
|
Мы не обработали этот случай, поэтому наша программа вылетала со следующим сообщением об ошибке:
1
2
3
4
5
6
|
Traceback (most recent call last):
File «addNumber.py», line 4, in <module>
addNumbers(», 10)
File «addNumber.py», line 2, in addNumbers
print a + b
TypeError: cannot concatenate ‘str’ and ‘int’ objects
|
Мы можем решить вышеуказанную проблему, проверив, являются ли переданные параметры целыми. Но это не решит проблему. Что если код сломается по какой-то другой причине и приведет к сбою программы? Работа с программой, которая дает сбой при обнаружении ошибки, не является хорошим зрением. Даже если обнаружена неизвестная ошибка, код должен быть достаточно надежным, чтобы корректно обработать сбой и дать пользователю понять, что что-то не так.
Обработка исключений с помощью Try and Except
В Python мы используем операторы try
и exception для обработки исключений. Всякий раз, когда код выходит из строя, генерируется исключение без сбоя программы. Давайте изменим программу добавления номеров, включив в нее операторы try
и except
.
1
2
3
4
5
6
7
|
def addNumbers(a, b):
try:
return a + b
except Exception as e:
return ‘Error occurred : ‘ + str(e)
print addNumbers(», 10)
|
Python будет обрабатывать весь код внутри оператора try
и except
. При обнаружении ошибки управление передается блоку except
, пропуская код между ними.
Как видно из вышеприведенного кода, мы переместили наш код в оператор try
и except
. Попробуйте запустить программу, и она должна выдать сообщение об ошибке вместо сбоя программы. Причина исключения также возвращается в виде сообщения об исключении.
Вышеуказанный метод обрабатывает неожиданные исключения. Давайте посмотрим, как обрабатывать ожидаемое исключение. Предположим, что мы пытаемся прочитать определенный файл с помощью нашей программы Python, но файл не существует. В этом случае мы обработаем исключение и дадим пользователю знать, что файл не существует, когда это происходит. Посмотрите на код чтения файла:
1
2
3
4
5
6
7
8
|
try:
try:
with open(‘fname’) as f:
content = f.readlines()
except IOError as e:
print str(e)
except Exception as e:
print str(e)
|
В приведенном выше коде мы обрабатывали чтение файла в обработчике исключений IOError. Если код не работает из-за недоступности файла fname
, ошибка будет обработана в обработчике IOError
. Подобно исключениям IOError
, существует множество стандартных исключений, таких как Arithmetic
, OverflowError
и ImportError
, чтобы назвать несколько.
Несколько исключений
Мы можем обрабатывать несколько исключений одновременно, используя стандартные исключения, как показано ниже:
1
2
3
4
5
6
|
try:
with open(‘fname’) as f:
content = f.readlines()
printb
except (IOError,NameError) as e:
print str(e)
|
Приведенный выше код NameError
исключения NameError
и NameError
при выполнении программы.
finally
пункт
Предположим, что мы используем определенные ресурсы в нашей программе Python. Во время выполнения программы произошла ошибка, и она была выполнена только наполовину. В этом случае ресурс будет излишне задержан. Мы можем очистить такие ресурсы, используя предложение finally
. Посмотрите на приведенный ниже код:
1
2
3
4
5
6
7
8
|
try:
filePointer = open(‘fname’,’r’)
try:
content = filePointer.readline()
finally:
filePointer.close()
except IOError as e:
print str(e)
|
Если во время выполнения вышеуказанного кода возникает исключение при чтении файла, filePointer
будет закрыт в блоке finally
.
Вход в Python
Когда что-то идет не так внутри приложения, становится легче отлаживать, если мы знаем источник ошибки. Когда возникает исключение, мы можем зарегистрировать необходимую информацию, чтобы отследить проблему. Python предоставляет простую и мощную библиотеку журналов. Давайте посмотрим, как использовать логирование в Python.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
import logging
# initialize the log settings
logging.basicConfig(filename=’app.log’,level=logging.INFO)
try:
logging.info(‘Trying to open the file’)
filePointer = open(‘appFile’,’r’)
try:
logging.info(‘Trying to read the file content’)
content = filePointer.readline()
finally:
filePointer.close()
except IOError as e:
logging.error(‘Error occurred ‘ + str(e))
|
Как видно из приведенного выше кода, сначала нам нужно импортировать библиотеку Python для ведения журнала, а затем инициализировать средство ведения журнала с именем файла журнала и уровнем ведения журнала. Существует пять уровней ведения журнала: DEBUG, INFO, WARNING, ERROR и CRITICAL. Здесь мы установили уровень ведения журнала на INFO, следовательно, журналы INFO и выше будут регистрироваться.
Получение трассировки стека
В приведенном выше коде у нас был один программный файл, поэтому было проще выяснить, где произошла ошибка. Но что мы делаем, когда задействованы несколько программных файлов? В таком случае получение трассировки стека ошибки помогает найти источник ошибки. Трассировка стека исключения может быть зарегистрирована как показано:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
import logging
# initialize the log settings
logging.basicConfig(filename = ‘app.log’, level = logging.INFO)
try:
filePointer = open(‘appFile’,’r’)
try:
content = filePointer.readline()
finally:
filePointer.close()
except IOError as e:
logging.exception(str(e))
|
Если вы попытаетесь запустить вышеуказанную программу, при возникновении исключения в файле журнала будет зарегистрирована следующая ошибка:
1
2
3
4
5
|
ERROR:root:[Errno 2] No such file or directory: ‘appFile’
Traceback (most recent call last):
File «readFile.py», line 7, in <module>
filePointer = open(‘appFile’,’r’)
IOError: [Errno 2] No such file or directory: ‘appFile’
|
Завершение
В этом уроке мы увидели, как начать работу с ошибками в Python и использовать модуль регистрации для регистрации ошибок. Мы видели использование операторов try
, except
и finally
, которые весьма полезны при работе с ошибками в Python. Для более подробной информации, я бы рекомендовал прочитать официальную документацию по ведению журнала . Также ознакомьтесь с документацией по обработке исключений в Python .
Дайте нам знать ваши мысли в комментариях ниже.