Будучи программистом, при разработке программного обеспечения вы неизбежно столкнетесь с ошибками. Это может быть что угодно – от логических ошибок, которые могут привести к самым неожиданным результатам, и ошибок, которые возникают в случае, если вы пренебрегаете правилами языка программирования, до ошибок, которые возникают при выполнении программы. Такие ошибки, как правило называют багами.
Баги – вездесущи, они есть в каждом языке программирования, и совершенно неважно, насколько язык прост в изучении и применении.
Например, если мы говорим о Python, то этот язык делает акцент на удобстве в чтении, придерживается выразительного синтаксиса, и его считают довольно простым с точки зрения изучения и применения в сравнении с другими языками программирования. Однако это вовсе не означает, что вы застрахованы от ошибок при программировании на Python.
Так как ошибки – это неотъемлемая часть работы программистов, было бы неплохо узнать о том, какие есть типы ошибок и почему они возникают, чтобы понимать, что с ними делать. Таким образом вы можете избежать возникновения ошибок при программировании (или хотя бы свести их к минимуму). Кроме того, вы узнаете, как можно устранить эти ошибки, когда они возникают.
Вот некоторые распространенные ошибки в Python, с которыми вы можете столкнуться при программировании на этом языке.
1. SyntaxError (синтаксическая ошибка)
Синтаксическая ошибка – это ошибка, возникающая при написании кода, который нарушает правила используемого вами языка программирования. В результате у вас в коде появляется недопустимая строка.
Так, например, в Python, когда вы выводите строку, вы должны заключать ее в кавычки. Если этого не сделать, вы получите синтаксическую ошибку.
Кроме того, синтаксическая ошибка может возникнуть тогда, когда вы пропустили открывающие или закрывающие круглые, квадратные или фигурные скобки, когда вы допустили опечатку в ключевых словах или именах функций, когда вы пропустили двоеточие в конце оператора управления потоком данных или обязательные операторы в выражениях.
В основном синтаксические ошибки возникают, когда вы нарушаете правила написания кода на Python.
## syntax error arising from missing quotation mark
## around the string being printed
{ ## синтаксическая ошибка возникает из-за отсутствия
## кавычек у строки, которую мы собираемся печатать }
print("Hello World)
age = 20
## Syntax error arising from missing colon in an if statement
{ ## Синтаксическая ошибка возникает из-за отсутствия двоеточия в операторе if }
if age > 18
print("Age is over 18")
## Syntax error because '(' was never closed
{ ## Синтаксическая ошибка из-за незакрытых круглых скобок }
def square(x:
return x * x
print(square(4))
После того, как вы выполните код, приведенный выше, вы увидите вот такое сообщение об ошибке:
Сообщение об ошибке при запуске данного кода буде выглядеть следующим образом:
File "/home/madici/Desktop/helloworld.py", line 1
print("Hello World)
^
SyntaxError: unterminated string literal (detected at line 1)
Для того, чтобы устранить эту ошибку, перепишите код правильно, как показано ниже:
print("Hello World")
age = 20
if age > 18:
print("Age is over 18")
def square(x):
return x * x
print(square(4))
2. IndentationError (ошибка отступа)
Для того, чтобы разделить блоки кода, такие языки, как Java, C и C++, используют фигурные скобки. А вот Python для определения иерархии и структуры блоков кода использует отступы. Например, когда вы пишете оператор управления в Java, весь код, который должен быть выполнен при выполнении условия, заключен в фигурные скобки.
Но если мы говорим о Python, то здесь блок кода будет обозначен с помощью отступов. Стандартный отступ в Python – это четыре пробела или один символ табуляции. Впрочем, количество пробелов не имеет значения, если оно остается постоянным на протяжении всего кода.
Если вы – программист, и работаете с Python, то, скорее всего, вы столкнетесь с ошибками отступа. Например, это может произойти, когда вы забудете добавить необходимый отступ (например, при написании операторов управления или функций), когда для создания отступов вы используете и символ табуляции, и пробелы (это сбивает с толку интерпретатор), когда вы ставите отступы там, где не нужно, или, когда вы используете в своей кодовой базе разные отступы.
Ниже приведен пример, при запуске которого вы получите ошибку отступа:
age = 20
if age > 18:
print("Age is greater than 18")
print("You're allowed to drive")
else:
print("Age is less than 18")
Сообщения об ошибках продемонстрированы ниже:
Сообщение об ошибке при запуске данного кода буде выглядеть следующим образом:
File "/home/madici/Desktop/helloworld.py", line 3
print("Age is greater than 18")
^
IndentationError: expected an indented block after 'if' statement on line 2
Для того, чтобы исправить эту ошибку, добавьте отступ в строке, которая идет после оператора if (так как он там нужен), и убедитесь в том, что все отступы в вашем коде одинаковы:
age = 20
if age > 18:
print("Age is greater than 18")
print("You're allowed to drive")
else:
print("Age is less than 18")
3. TypeError (ошибка несоответствия типов)
TypeError – это исключение, которое возникает, когда вы пытаетесь выполнить операцию, используя при этом несовместимый тип данных. Например, если вы попытаетесь сложить или объединить строку и целое число, то получите ошибку несоответствия типов.
Кроме того, такие ошибки могут возникать, когда вы используете функции или методы с неправильными типами данных, когда вы пытаетесь использовать нецелочисленный индекс для того, чтобы получить доступ к элементам в некотором итерируемом списке или чём-то подобном, или когда вы пытаетесь выполнить итеративный обход по объекту, который не является итерируемым.
Если брать в целом, то любая операция, для которой используется неверный тип данных, выдаст ошибку TypeError.
Ниже приведены примеры операций, которые могут выдать такую ошибку:
# Type Error resulting from concatenating a string an an integer
{ # Ошибка несоответствия типов возникает в результате объединения строки и целого числа }
age = 25
message = "I am " + age + " years old."
list1 = [1, "hello", 5, "world", 18, 2021]
#Type errors resulting from wrong usage of builtin in methods
{ # Ошибка несоответствия типов возникает из-за неправильного использования встроенных методов }
print(sum(list1))
#TypeError resulting from adding a string and an integer
{ # Ошибка несоответствия типов возникает в результате сложения строки и целого числа }
num1 = 10
num2 = "16"
print(num1 + num2)
#TypeError resulting from using a non integer index
{ # Ошибка несоответствия типов возникает в результате использования нецелочисленного индекса }
list2 = ["hello", "from", "the", "other", "side"]
print(list2["1"])
Сообщения об ошибках продемонстрированы ниже:
Пример ошибки TypeError, возникающей в результате запуска кода, приведенного выше:
File "/home/madici/Desktop/helloworld.py", line 3, in <module>
message = "I am " + age + " years old."
~~~~~~~~^~~~~
TypeError: can only concatenate str (not "int") to str
Для того, чтобы устранить эти ошибки, замените типы данных на корректные или выполните преобразование типов:
age = 25
message = "I am " + str(age) + " years old."
list1 = [1, 5, 18, 2021]
print(sum(list1))
num1 = 10
num2 = "16"
print(num1 + int(num2))
list2 = ["hello", "from", "the", "other", "side"]
print(list2[1])
4. AttributeError (ошибка доступа к атрибуту)
AttributeError возникает тогда, когда вы пытаетесь использовать атрибут, которого у объекта нет, или когда вы вызываете метод, которого у объекта, для которого он вызывается, нет. Ошибка доступа к атрибуту показывает, что атрибут или метод, который вы вызываете для объекта, не существует.
Например, если вы вызовете метод, предназначенный для строковых данных, для целого числа, то вы получите ошибку AttributeError, так как для данного типа объекта (для которого вызывается метод) этот метод не существует.
Рассмотрим пример ниже. Здесь мы используем метод capitalize() для целого числа. По сути этот метод используется для преобразования первой буквы строки в верхний регистр, так что в качестве результата вы получите ошибку доступа к атрибуту, потому то у целых чисел нет метода capitalize().
# AttributeError arising from calling capitalize() on an int value
{ # Ошибка доступа к атрибуту возникает из-за вызова метода capitalize() для целого числа }
num = 1445
cap = num.capitalize()
print(cap)
Запустив этот код, вы получите вот такое сообщение об ошибке:
Сообщение об ошибке доступа к атрибуту, возникшей после запуска кода выше, выглядит следующим образом:
File "/home/madici/Desktop/helloworld.py", line 3, in <module>
cap = num.capitalize()
^^^^^^^^^^^^^^
AttributeError: 'int' object has no attribute 'capitalize'
Для того, чтобы исправить эту ошибку, убедитесь в том, что метод, который вы пытаетесь вызвать, или атрибут, к которому вы хотите получить доступ, существует для того типа объекта, для которого вы его вызываете. В данном случае ошибку можно исправить, просто вызвав метод capitalize() для строкового типа данных:
5. ImportError (ошибка импорта)
ImportError возникает тогда, когда вы пытаетесь импортировать модуль, который не может быть найден или который недоступен в вашей среде. Вполне возможно, что вы его еще не установили, неправильно указали путь к нему или ошиблись при написании названия модуля, который вы хотите установить.
У ошибки импорта есть один единственный подвид - ModuleNotFoundError. Это ошибка, которая возникает тогда, когда вы пытаетесь импортировать модуль, который не может быть найден.
Например, код, который мы привели ниже, пытается импортировать библиотеку анализа данных pandas. А так как этот модуль еще не был установлен, код выдает ошибку.
В результате вы увидите вот такое сообщение об ошибке:
File "/home/madici/Desktop/helloworld.py", line 1, in <module>
import pandas
ModuleNotFoundError: No module named 'pandas'
Для того, чтобы исправить эту ошибку, убедитесь в том, что модули, которые вы пытаетесь импортировать, были установлены. В случае, если это не поможет, проверьте корректность написания имени модуля и правильность пути к файлу, который обеспечивает доступ к модулю.
6. ValueError (ошибка использования некорректного значения)
Это исключение, которое возникает тогда, когда функция получает значение правильного типа, но это значение не является подходящим. Например, если вы передадите функции Math.sqrt() отрицательно число, то получите ошибку ValueError, так как эта функция предназначена для нахождения квадратного корня числа.
Конечно, тип значения будет правильным, то есть числовым, но тот факт, что значение отрицательное, делает его неподходящим.
Если вы передадите функции int() (которая преобразовывает строку в число) строку, которая не является числовым строковым значением, то она вернет ошибку ValueError. Если вы передадите ей «123» или «45», то ошибки не будет, так как эти строки могут быть преобразованы в соответствующие числовые значения.
Но если вы попытаетесь передать строку, которая не является числовым строковым значением, например, «Hello», то вы получите ошибку ValueError. А все потому, что несмотря на то, что «Hello» - это строка, она не имеет целочисленного эквивалента.
Ниже приведен пример кода, который выдает ошибку ValueError:
# Value error resulting from inappropriate int value in sqrt()
{ # Ошибка использования некорректного значения возникает в результате попытки передать неподходящее целочисленное значение в sqrt() }
import math
num = -64
root = math.sqrt(num)
print(root)
# Value error resulting from passing a string with no integer
# equivalent into int() function
{ # Ошибка использования некорректного значения возникает из-за передачи
# в функцию int() строки, у которой нет целочисленного эквивалента }
numString = "Hello"
num = int(numString)
print(num)
Вот ошибки, которые возникают в результате запуска этого кода:
В результате появится вот такое сообщение об ошибке:
File "/home/madici/Desktop/helloworld.py", line 4, in <module>
root = math.sqrt(num)
^^^^^^^^^^^^^^
ValueError: math domain error
Для того, чтобы исправить эту ошибку, вам нужно передать в функцию подходящее значение:
import math
num = 64
root = math.sqrt(num)
print(root)
numString = "5231"
num = int(numString)
print(num)
7. IOError (ошибка ввода-вывода)
IOError (ошибка ввода/вывода) – это исключение, которые возникает в случае сбоя операции ввода или операции вывода. Это может произойти из-за попытки получит доступ к файлу, который не существует, для доступа к которому у вас недостаточно прав иди который на данный момент задействован в других операциях, или из-за недостаточного объема памяти на диске вашего устройства.
Такую ошибку могут выдавать такие методы, как open(), read(), write() и close(), которые чаще всего используются для работы с файлами.
Давайте рассмотрим код ниже, который пытается открыть несуществующий файл под названием «notes.txt». Этот код выдаст ошибку IOError, которая вызовет исключение FileNotFoundError:
При этом появится вот такое сообщение об ошибке:
File "/home/madici/Desktop/helloworld.py", line 2, in <module>
file1 = open("notes.txt", "r")
^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'notes.txt'
Для того, чтобы избежать таких ситуаций, все, что от вас требуется, это убедиться в том, что файл «notes.txt» существует в том каталоге, в котором вы запускаете терминал. Есть еще один способ, как можно исправить ошибку IOError. Для этого вам понадобиться блок try-except:
8. NameError (ошибка несуществующего имени)
NameError – это исключение, которое возникает, когда вы пытаетесь использовать переменную, функцию или модуль, которые не существуют, которые не определены в текущей области видимости или у которых нет значений.
Как правило, такая ошибка возникает тогда, когда вы делаете ошибки в именах переменных или функций или когда используете их до того, как они буду определены. Если вы будете пытаться использовать модуль, не импортировав его, вы также получите ошибку NamError.
Код ниже приведет к исключению NameError:
# name error arises because the math module has not been imported
{ # ошибка несуществующего имени возникает из-за того, что вы не импортировали модуль math }
num = 64
root = math.sqrt(64)
print(root)
# NameError arises because x is used before it is defined
{ # ошибка несуществующего имени возникает из-за того, что переменная x используется до того, как была определена }
y = 23
print(x)
#NameEror because function name is not defined
{ # ошибка несуществующего имени возникает из-за неопределенного имени функции }
def greet():
print("Good morning")
great() #ameError: name 'great' is not defined
И вы получите вот такие сообщения об ошибках:
Примерно вот так выглядит сообщение об ошибке NameError:
File "/home/madici/Desktop/helloworld.py", line 3, in <module>
root = math.sqrt(64)
^^^^
NameError: name 'math' is not defined
Для того, чтобы исправить ошибку NameError, убедитесь, что вы импортировали модули, которые используете, что вы не используете переменные или функции до того, как они были определены, и не наделали ошибок в именах функций и переменных:
import math
num = 64
root = math.sqrt(64)
print(root)
y = 23
print(y)
def greet():
print("Good morning")
greet()
9. IndexError (ошибка несуществующего индекса)
IndexError – это исключение, которое возникает в том случае, если вы пытаетесь получить доступ к элементу списка или кортежа с помощью индекса, который находится вне диапазона. Давайте посмотрим на следующий список:
list1 = [1, 2, 3, 4, 5]
В этом списке пять элементов. В Python индексы начинаются с нуля. А значит, что список, приведенный выше, имеет следующие индексы: 0, …, n-1, где n – это количество элементов в списке. В данном случае индексы меняются от 0 до 4.
Если вы попытаетесь получить доступ к элементу, чей индекс больше 4, то вы увидите ошибку IndexError, так как этот индекс находиться вне диапазона списка, в котором находится элемент, к которому вы хотите получить доступ. Ниже приведен код, который выдаст ошибку IndexError:
list1 = [1, 2, 3, 4, 5]
item = list1[6] #IndexError because the list index is out of range { # ошибка несуществующего индекса возникает из-за того, что индекс находится вне диапазона списка }
print(item)
Вот так будет выглядеть эта ошибка:
Вот так будет выглядеть сообщение об ошибке IndexError:
File "/home/madici/Desktop/helloworld.py", line 2, in <module>
item = list1[6] #IndexError because the list index is out of range
~~~~~^^^
IndexError: list index out of range
Чтобы избежать таких ошибок, лучше всего использовать функции range() и len(). Таким образом вы сможете убедиться в том, что элементы, к которым вы хотите получить доступ, находятся в пределах диапазона списка:
list1 = [1, 2, 3, 4, 5]
for i in range(len(list1)):
print(list1[i])
10. KeyError (ошибка отсутствующего ключа)
KeyError – это исключение, которое возникает тогда, когда вы пытаетесь получить доступ к элементу словаря с помощью ключа, которого в словаре нет. Давайте посмотрим на следующий словарь:
cities = {"Canada": "Ottawa", "USA": "Washington", "Italy": "Rome"}
Здесь ключи – это «Canada», «USA», «Italy». С помощью эти трех ключей вы можете получить доступ к элементам из словаря, в котором хранятся города. Но если вы попробуете получить доступ к элементу с помощью какого-то несуществующего ключа, например, «Brazil», то получите ошибку KeyError:
Вот так будет выглядеть сообщение об ошибке KeyError:
File "/home/madici/Desktop/helloworld.py", line 6, in <module>
print(cities["Brazil"])
~~~~~~^^^^^^^^^^
KeyError: 'Brazil'
Для того, чтобы таких ошибок не было, убедитесь, что ключи, которые вы используете для доступа к элементам словаря, действительно существуют в рамках этого словаря. Для этого вы можете воспользоваться оператором if…else:
cities = {"Canada": "Ottawa", "USA": "Washington", "Italy": "Rome"}
country = "Canada"
if country in cities:
print("The capital city of " + country + " is " + cities[country])
else:
print("The key " + country + " is not present in the cities dictionary")
При таком подходе вы сможете избежать возникновения ошибок KeyError при попытке получить доступ к элементам словаря.
Заключение
Когда вы пишете программы на Python, не имеет значения, каков уровень ваших знаний, вы обязательно столкнетесь со ошибками. Именно поэтому, очень важно ознакомиться с различными типами ошибок, которые мы продемонстрировали в этой статье. Тогда вы будете уверены в том, что сможете исправить их, когда они возникнут.