TypeError is one among the several standard Python exceptions. TypeError is raised whenever an operation is performed on an incorrect/unsupported object type. For example, using the + (addition) operator on a string and an integer value will raise TypeError.
Examples
The general causes for TypeError being raised are:
1. Unsupported operation between two types:
In the following example, the variable ‘geek’ is a string and the variable ‘num’ is an integer. The + (addition) operator cannot be used between these two types and hence TypeError is raised.
Python3
geek
=
"Geeks"
num
=
4
print
(geek
+
num
+
geek)
Output :
TypeError: must be str, not int
2. Calling a non-callable identifier:
In the below example code, the variable ‘geek’ is a string and is non-callable in this context. Since it is called in the print statement, TypeError is raised.
Python3
geek
=
"GeeksforGeeks"
print
(geek())
Output :
TypeError: 'str' object is not callable
3. Incorrect type of list index:
In Python, list indices must always be an integer value. Since the index value used in the following code is a string, it raises TypeError.
Python3
geeky_list
=
[
"geek"
,
"GeeksforGeeks"
,
"geeky"
,
"geekgod"
]
index
=
"1"
print
(geeky_list[index])
Output :
TypeError: list indices must be integers or slices, not str
4. Iterating through a non-iterative identifier:
In the following code, the value 1234.567890 is a floating-point number and hence it is non-iterative. Forcing Python to iterate on a non-iterative identifier will raise TypeError.
Python3
for
geek
in
1234.567890
:
print
(geek)
Output :
TypeError: 'float' object is not iterable
Handling TypeError
TypeErrors are raised mostly in situations where the programmer fails to check the type of object before performing an operation on them. They can be handled specifically by mentioning them in the except block. In the following example, when one of the indices is found to be an incorrect type, an exception is raised and handled by the program.
Python3
geeky_list
=
[
"Geeky"
,
"GeeksforGeeks"
,
"SuperGeek"
,
"Geek"
]
indices
=
[
0
,
1
,
"2"
,
3
]
for
i
in
range
(
len
(indices)):
try
:
print
(geeky_list[indices[i]])
except
TypeError:
print
(
"TypeError: Check list of indices"
)
Output :
Geeky GeeksforGeeks TypeError: Check list of indices Geek
TypeError is one among the several standard Python exceptions. TypeError is raised whenever an operation is performed on an incorrect/unsupported object type. For example, using the + (addition) operator on a string and an integer value will raise TypeError.
Examples
The general causes for TypeError being raised are:
1. Unsupported operation between two types:
In the following example, the variable ‘geek’ is a string and the variable ‘num’ is an integer. The + (addition) operator cannot be used between these two types and hence TypeError is raised.
Python3
geek
=
"Geeks"
num
=
4
print
(geek
+
num
+
geek)
Output :
TypeError: must be str, not int
2. Calling a non-callable identifier:
In the below example code, the variable ‘geek’ is a string and is non-callable in this context. Since it is called in the print statement, TypeError is raised.
Python3
geek
=
"GeeksforGeeks"
print
(geek())
Output :
TypeError: 'str' object is not callable
3. Incorrect type of list index:
In Python, list indices must always be an integer value. Since the index value used in the following code is a string, it raises TypeError.
Python3
geeky_list
=
[
"geek"
,
"GeeksforGeeks"
,
"geeky"
,
"geekgod"
]
index
=
"1"
print
(geeky_list[index])
Output :
TypeError: list indices must be integers or slices, not str
4. Iterating through a non-iterative identifier:
In the following code, the value 1234.567890 is a floating-point number and hence it is non-iterative. Forcing Python to iterate on a non-iterative identifier will raise TypeError.
Python3
for
geek
in
1234.567890
:
print
(geek)
Output :
TypeError: 'float' object is not iterable
Handling TypeError
TypeErrors are raised mostly in situations where the programmer fails to check the type of object before performing an operation on them. They can be handled specifically by mentioning them in the except block. In the following example, when one of the indices is found to be an incorrect type, an exception is raised and handled by the program.
Python3
geeky_list
=
[
"Geeky"
,
"GeeksforGeeks"
,
"SuperGeek"
,
"Geek"
]
indices
=
[
0
,
1
,
"2"
,
3
]
for
i
in
range
(
len
(indices)):
try
:
print
(geeky_list[indices[i]])
except
TypeError:
print
(
"TypeError: Check list of indices"
)
Output :
Geeky GeeksforGeeks TypeError: Check list of indices Geek
Обработка ошибок увеличивает отказоустойчивость кода, защищая его от потенциальных сбоев, которые могут привести к преждевременному завершению работы.
Прежде чем переходить к обсуждению того, почему обработка исключений так важна, и рассматривать встроенные в Python исключения, важно понять, что есть тонкая грань между понятиями ошибки и исключения.
Ошибку нельзя обработать, а исключения Python обрабатываются при выполнении программы. Ошибка может быть синтаксической, но существует и много видов исключений, которые возникают при выполнении и не останавливают программу сразу же. Ошибка может указывать на критические проблемы, которые приложение и не должно перехватывать, а исключения — состояния, которые стоит попробовать перехватить. Ошибки — вид непроверяемых и невозвратимых ошибок, таких как OutOfMemoryError
, которые не стоит пытаться обработать.
Обработка исключений делает код более отказоустойчивым и помогает предотвращать потенциальные проблемы, которые могут привести к преждевременной остановке выполнения. Представьте код, который готов к развертыванию, но все равно прекращает работу из-за исключения. Клиент такой не примет, поэтому стоит заранее обработать конкретные исключения, чтобы избежать неразберихи.
Ошибки могут быть разных видов:
- Синтаксические
- Недостаточно памяти
- Ошибки рекурсии
- Исключения
Разберем их по очереди.
Синтаксические ошибки (SyntaxError)
Синтаксические ошибки часто называют ошибками разбора. Они возникают, когда интерпретатор обнаруживает синтаксическую проблему в коде.
Рассмотрим на примере.
a = 8
b = 10
c = a b
File "", line 3
c = a b
^
SyntaxError: invalid syntax
Стрелка вверху указывает на место, где интерпретатор получил ошибку при попытке исполнения. Знак перед стрелкой указывает на причину проблемы. Для устранения таких фундаментальных ошибок Python будет делать большую часть работы за программиста, выводя название файла и номер строки, где была обнаружена ошибка.
Недостаточно памяти (OutofMemoryError)
Ошибки памяти чаще всего связаны с оперативной памятью компьютера и относятся к структуре данных под названием “Куча” (heap
). Если есть крупные объекты (или) ссылки на подобные, то с большой долей вероятности возникнет ошибка OutofMemory
. Она может появиться по нескольким причинам:
- Использование 32-битной архитектуры Python (максимальный объем выделенной памяти невысокий, между 2 и 4 ГБ);
- Загрузка файла большого размера;
- Запуск модели машинного обучения/глубокого обучения и много другое;
Обработать ошибку памяти можно с помощью обработки исключений — резервного исключения. Оно используется, когда у интерпретатора заканчивается память и он должен немедленно остановить текущее исполнение. В редких случаях Python вызывает OutofMemoryError
, позволяя скрипту каким-то образом перехватить самого себя, остановить ошибку памяти и восстановиться.
Но поскольку Python использует архитектуру управления памятью из языка C (функция malloc()
), не факт, что все процессы восстановятся — в некоторых случаях MemoryError
приведет к остановке. Следовательно, обрабатывать такие ошибки не рекомендуется, и это не считается хорошей практикой.
Ошибка рекурсии (RecursionError)
Эта ошибка связана со стеком и происходит при вызове функций. Как и предполагает название, ошибка рекурсии возникает, когда внутри друг друга исполняется много методов (один из которых — с бесконечной рекурсией), но это ограничено размером стека.
Все локальные переменные и методы размещаются в стеке. Для каждого вызова метода создается стековый кадр (фрейм), внутрь которого помещаются данные переменной или результат вызова метода. Когда исполнение метода завершается, его элемент удаляется.
Чтобы воспроизвести эту ошибку, определим функцию recursion
, которая будет рекурсивной — вызывать сама себя в бесконечном цикле. В результате появится ошибка StackOverflow
или ошибка рекурсии, потому что стековый кадр будет заполняться данными метода из каждого вызова, но они не будут освобождаться.
def recursion():
return recursion()
recursion()
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
in
----> 1 recursion()
in recursion()
1 def recursion():
----> 2 return recursion()
... last 1 frames repeated, from the frame below ...
in recursion()
1 def recursion():
----> 2 return recursion()
RecursionError: maximum recursion depth exceeded
Ошибка отступа (IndentationError)
Эта ошибка похожа по духу на синтаксическую и является ее подвидом. Тем не менее она возникает только в случае проблем с отступами.
Пример:
for i in range(10):
print('Привет Мир!')
File "", line 2
print('Привет Мир!')
^
IndentationError: expected an indented block
Исключения
Даже если синтаксис в инструкции или само выражение верны, они все равно могут вызывать ошибки при исполнении. Исключения Python — это ошибки, обнаруживаемые при исполнении, но не являющиеся критическими. Скоро вы узнаете, как справляться с ними в программах Python. Объект исключения создается при вызове исключения Python. Если скрипт не обрабатывает исключение явно, программа будет остановлена принудительно.
Программы обычно не обрабатывают исключения, что приводит к подобным сообщениям об ошибке:
Ошибка типа (TypeError)
a = 2
b = 'PythonRu'
a + b
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
in
1 a = 2
2 b = 'PythonRu'
----> 3 a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Ошибка деления на ноль (ZeroDivisionError)
10 / 0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
in
----> 1 10 / 0
ZeroDivisionError: division by zero
Есть разные типы исключений в Python и их тип выводится в сообщении: вверху примеры TypeError
и ZeroDivisionError
. Обе строки в сообщениях об ошибке представляют собой имена встроенных исключений Python.
Оставшаяся часть строки с ошибкой предлагает подробности о причине ошибки на основе ее типа.
Теперь рассмотрим встроенные исключения Python.
Встроенные исключения
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
Прежде чем переходить к разбору встроенных исключений быстро вспомним 4 основных компонента обработки исключения, как показано на этой схеме.
Try
: он запускает блок кода, в котором ожидается ошибка.Except
: здесь определяется тип исключения, который ожидается в блокеtry
(встроенный или созданный).Else
: если исключений нет, тогда исполняется этот блок (его можно воспринимать как средство для запуска кода в том случае, если ожидается, что часть кода приведет к исключению).Finally
: вне зависимости от того, будет ли исключение или нет, этот блок кода исполняется всегда.
В следующем разделе руководства больше узнаете об общих типах исключений и научитесь обрабатывать их с помощью инструмента обработки исключения.
Ошибка прерывания с клавиатуры (KeyboardInterrupt)
Исключение KeyboardInterrupt
вызывается при попытке остановить программу с помощью сочетания Ctrl + C
или Ctrl + Z
в командной строке или ядре в Jupyter Notebook. Иногда это происходит неумышленно и подобная обработка поможет избежать подобных ситуаций.
В примере ниже если запустить ячейку и прервать ядро, программа вызовет исключение KeyboardInterrupt
. Теперь обработаем исключение KeyboardInterrupt
.
try:
inp = input()
print('Нажмите Ctrl+C и прервите Kernel:')
except KeyboardInterrupt:
print('Исключение KeyboardInterrupt')
else:
print('Исключений не произошло')
Исключение KeyboardInterrupt
Стандартные ошибки (StandardError)
Рассмотрим некоторые базовые ошибки в программировании.
Арифметические ошибки (ArithmeticError)
- Ошибка деления на ноль (Zero Division);
- Ошибка переполнения (OverFlow);
- Ошибка плавающей точки (Floating Point);
Все перечисленные выше исключения относятся к классу Arithmetic
и вызываются при ошибках в арифметических операциях.
Деление на ноль (ZeroDivisionError)
Когда делитель (второй аргумент операции деления) или знаменатель равны нулю, тогда результатом будет ошибка деления на ноль.
try:
a = 100 / 0
print(a)
except ZeroDivisionError:
print("Исключение ZeroDivisionError." )
else:
print("Успех, нет ошибок!")
Исключение ZeroDivisionError.
Переполнение (OverflowError)
Ошибка переполнение вызывается, когда результат операции выходил за пределы диапазона. Она характерна для целых чисел вне диапазона.
try:
import math
print(math.exp(1000))
except OverflowError:
print("Исключение OverFlow.")
else:
print("Успех, нет ошибок!")
Исключение OverFlow.
Ошибка утверждения (AssertionError)
Когда инструкция утверждения не верна, вызывается ошибка утверждения.
Рассмотрим пример. Предположим, есть две переменные: a
и b
. Их нужно сравнить. Чтобы проверить, равны ли они, необходимо использовать ключевое слово assert
, что приведет к вызову исключения Assertion
в том случае, если выражение будет ложным.
try:
a = 100
b = "PythonRu"
assert a == b
except AssertionError:
print("Исключение AssertionError.")
else:
print("Успех, нет ошибок!")
Исключение AssertionError.
Ошибка атрибута (AttributeError)
При попытке сослаться на несуществующий атрибут программа вернет ошибку атрибута. В следующем примере можно увидеть, что у объекта класса Attributes
нет атрибута с именем attribute
.
class Attributes(obj):
a = 2
print(a)
try:
obj = Attributes()
print(obj.attribute)
except AttributeError:
print("Исключение AttributeError.")
2
Исключение AttributeError.
Ошибка импорта (ModuleNotFoundError)
Ошибка импорта вызывается при попытке импортировать несуществующий (или неспособный загрузиться) модуль в стандартном пути или даже при допущенной ошибке в имени.
import nibabel
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
in
----> 1 import nibabel
ModuleNotFoundError: No module named 'nibabel'
Ошибка поиска (LookupError)
LockupError
выступает базовым классом для исключений, которые происходят, когда key
или index
используются для связывания или последовательность списка/словаря неверна или не существует.
Здесь есть два вида исключений:
- Ошибка индекса (
IndexError
); - Ошибка ключа (
KeyError
);
Ошибка ключа
Если ключа, к которому нужно получить доступ, не оказывается в словаре, вызывается исключение KeyError
.
try:
a = {1:'a', 2:'b', 3:'c'}
print(a[4])
except LookupError:
print("Исключение KeyError.")
else:
print("Успех, нет ошибок!")
Исключение KeyError.
Ошибка индекса
Если пытаться получить доступ к индексу (последовательности) списка, которого не существует в этом списке или находится вне его диапазона, будет вызвана ошибка индекса (IndexError: list index out of range python).
try:
a = ['a', 'b', 'c']
print(a[4])
except LookupError:
print("Исключение IndexError, индекс списка вне диапазона.")
else:
print("Успех, нет ошибок!")
Исключение IndexError, индекс списка вне диапазона.
Ошибка памяти (MemoryError)
Как уже упоминалось, ошибка памяти вызывается, когда операции не хватает памяти для выполнения.
Ошибка имени (NameError)
Ошибка имени возникает, когда локальное или глобальное имя не находится.
В следующем примере переменная ans
не определена. Результатом будет ошибка NameError
.
try:
print(ans)
except NameError:
print("NameError: переменная 'ans' не определена")
else:
print("Успех, нет ошибок!")
NameError: переменная 'ans' не определена
Ошибка выполнения (Runtime Error)
Ошибка «NotImplementedError»
Ошибка выполнения служит базовым классом для ошибки NotImplemented
. Абстрактные методы определенного пользователем класса вызывают это исключение, когда производные методы перезаписывают оригинальный.
class BaseClass(object):
"""Опередляем класс"""
def __init__(self):
super(BaseClass, self).__init__()
def do_something(self):
# функция ничего не делает
raise NotImplementedError(self.__class__.__name__ + '.do_something')
class SubClass(BaseClass):
"""Реализует функцию"""
def do_something(self):
# действительно что-то делает
print(self.__class__.__name__ + ' что-то делает!')
SubClass().do_something()
BaseClass().do_something()
SubClass что-то делает!
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
in
14
15 SubClass().do_something()
---> 16 BaseClass().do_something()
in do_something(self)
5 def do_something(self):
6 # функция ничего не делает
----> 7 raise NotImplementedError(self.__class__.__name__ + '.do_something')
8
9 class SubClass(BaseClass):
NotImplementedError: BaseClass.do_something
Ошибка типа (TypeError)
Ошибка типа вызывается при попытке объединить два несовместимых операнда или объекта.
В примере ниже целое число пытаются добавить к строке, что приводит к ошибке типа.
try:
a = 5
b = "PythonRu"
c = a + b
except TypeError:
print('Исключение TypeError')
else:
print('Успех, нет ошибок!')
Исключение TypeError
Ошибка значения (ValueError)
Ошибка значения вызывается, когда встроенная операция или функция получают аргумент с корректным типом, но недопустимым значением.
В этом примере встроенная операция float
получат аргумент, представляющий собой последовательность символов (значение), что является недопустимым значением для типа: число с плавающей точкой.
try:
print(float('PythonRu'))
except ValueError:
print('ValueError: не удалось преобразовать строку в float: 'PythonRu'')
else:
print('Успех, нет ошибок!')
ValueError: не удалось преобразовать строку в float: 'PythonRu'
Пользовательские исключения в Python
В Python есть много встроенных исключений для использования в программе. Но иногда нужно создавать собственные со своими сообщениями для конкретных целей.
Это можно сделать, создав новый класс, который будет наследовать из класса Exception
в Python.
class UnAcceptedValueError(Exception):
def __init__(self, data):
self.data = data
def __str__(self):
return repr(self.data)
Total_Marks = int(input("Введите общее количество баллов: "))
try:
Num_of_Sections = int(input("Введите количество разделов: "))
if(Num_of_Sections < 1):
raise UnAcceptedValueError("Количество секций не может быть меньше 1")
except UnAcceptedValueError as e:
print("Полученная ошибка:", e.data)
Введите общее количество баллов: 10
Введите количество разделов: 0
Полученная ошибка: Количество секций не может быть меньше 1
В предыдущем примере если ввести что-либо меньше 1, будет вызвано исключение. Многие стандартные исключения имеют собственные исключения, которые вызываются при возникновении проблем в работе их функций.
Недостатки обработки исключений в Python
У использования исключений есть свои побочные эффекты, как, например, то, что программы с блоками try-except работают медленнее, а количество кода возрастает.
Дальше пример, где модуль Python timeit
используется для проверки времени исполнения 2 разных инструкций. В stmt1
для обработки ZeroDivisionError
используется try-except, а в stmt2
— if
. Затем они выполняются 10000 раз с переменной a=0
. Суть в том, чтобы показать разницу во времени исполнения инструкций. Так, stmt1
с обработкой исключений занимает больше времени чем stmt2
, который просто проверяет значение и не делает ничего, если условие не выполнено.
Поэтому стоит ограничить использование обработки исключений в Python и применять его в редких случаях. Например, когда вы не уверены, что будет вводом: целое или число с плавающей точкой, или не уверены, существует ли файл, который нужно открыть.
import timeit
setup="a=0"
stmt1 = '''
try:
b=10/a
except ZeroDivisionError:
pass'''
stmt2 = '''
if a!=0:
b=10/a'''
print("time=",timeit.timeit(stmt1,setup,number=10000))
print("time=",timeit.timeit(stmt2,setup,number=10000))
time= 0.003897680000136461
time= 0.0002797570000439009
Выводы!
Как вы могли увидеть, обработка исключений помогает прервать типичный поток программы с помощью специального механизма, который делает код более отказоустойчивым.
Обработка исключений — один из основных факторов, который делает код готовым к развертыванию. Это простая концепция, построенная всего на 4 блоках: try
выискивает исключения, а except
их обрабатывает.
Очень важно поупражняться в их использовании, чтобы сделать свой код более отказоустойчивым.
Introduction to Python TypeError
TypeError is a kind of error that python generates. We are trying to perform the operation of the wrong type of object. For example, if we are trying to do the square root of a number but we are passing a list instead of int, then TypeError will be generated by the python. This type of error is also generated when we are trying to perform the operation on the object, and it is not supported.
How to Avoid TypeError?
Python always checks the type of object we are passing for operation and whether a particular object type supports the operation. Python will throw a TypeError. We can avoid this error by adding an extra step or try-catch before such an operation. Suppose we want to join two lists. So before joining the operation, we can check the type of both the list that the user passes; if the type doesn’t match our requirement, we can pass a message to the user indicating wrong input and tell him to pass the proper input.
Examples of Python TypeError
Following are the examples are given below:
Example #1
Code:
list1 = [7,8,9,10]
list2 = 's';
result = list2.join(list1)
print(result)
Output:
As you can see in the above program, we have created a list of list1 and list2 as a string variable. Now we are trying to join the list1 with list2, but python returns the type error. Because list2 is of string type, and python is expecting each element of the list1 to be a string, but it’s an integer.
Example #2
Code:
list1 = ['7','8',9,10]
list2 = 's';
result = list2.join(list1)
print(result)
Output:
Now in the above, we have modified our first list, we have made the first two elements as a string, but the rest two elements are still int. So when we execute it, python still generates TypeError, as it says element index 2, i.e. the third element is still an integer. So now we have to make the rest two elements also as integers to work properly.
Example #3
Code:
list1 = ['7','8',9,10]
list2 = 's';
result = list2.join(str(a) for a in list1)
print(result)
Output:
In the above program, you can see inside the join function, we have converted each element of list1 into a string by typecasting. It will make sure each element is a string; if not, then it will be covert it. So in this way, we can avoid TypeError.
Example #4
Code:
a = 's';
b = 4;
c = a/b;
print(c)
Output:
In the above example, you can see that we have created two variables. One is holding an integer value, and another is holding a string or character value. Now we are trying to perform division between the variable and hold the result into the third variable and printing the result. But python will throw TypeError because an integer cannot be divided by string or character, the python was expecting integer value, so it throws TypeError.
Now in such cases, we know that we have to do division operation, and both variables should be an integer, so we have to handle it before performing such an operation.
Example #5
Code:
a = 's';
b = 4;
if(type(b) != int or type(a) != int):
print('One of the number is not integer')
else:
c = a/b;
print(c)
Output:
In this example, we can see that we have put the if condition checking the type of both the variables; if any of the variables is not an integer, then we are passing a message to the user to enter the values again. In this way, we can avoid TypeError.
Code:
a = 5;
b = 4;
if(type(b) != int or type(a) != int):
print('One of the number is not integer')
else:
c = a/b;
print(c)
Output:
This time our program worked correctly.
Example #6
Code:
list1 = 's';
list2 = [3, 4, 5, 8, 9];
print(list1 + list2)
Output:
In the above example, you can; we are trying to contact two variables. One is a holding string, and the other is a holding list. Python returns a type error because the string cannot be concatenated to the list. Python is expecting a list, so it returns a type error. So to avoid this, we can check the type of variable before executing the operation.
Code:
list1 = 's';
list2 = [3, 4, 5, 8, 9];
if(type(list1) != list or type(list2) != list):
print('One of the values is not list')
else:
print(list1 + list2)
Output:
In this example, we are checking the type of both the variables before contacting them; thus, we can avoid this type of error.
Recommended Articles
This is a guide to Python TypeError. Here we also discuss the introduction and how to avoid typeerror? Along with different examples and its code implementation. you may also have a look at the following articles to learn more –
- Python Constants
- Quick Sort in Python
- Python Concurrency
- Python argparse
В этом руководстве мы расскажем, как обрабатывать исключения в Python с помощью try
и except
. Рассмотрим общий синтаксис и простые примеры, обсудим, что может пойти не так, и предложим меры по исправлению положения.
Зачастую разработчик может предугадать возникновение ошибок при работе даже синтаксически и логически правильной программы. Эти ошибки могут быть вызваны неверными входными данными или некоторыми предсказуемыми несоответствиями.
Для обработки большей части этих ошибок как исключений в Python есть блоки try
и except
.
Для начала разберем синтаксис операторов try и except в Python. Общий шаблон представлен ниже:
try: # В этом блоке могут быть ошибки except <error type>: # Сделай это для обработки исключения; # выполняется, если блок try выбрасывает ошибку else: # Сделай это, если блок try выполняется успешно, без ошибок finally: # Этот блок выполняется всегда
Давайте посмотрим, для чего используются разные блоки.
Блок try
Блок try
— это блок кода, который вы хотите попробовать выполнить. Однако во время выполнения из-за какого-нибудь исключения могут возникнуть ошибки. Поэтому этот блок может не работать должным образом.
Блок except
Блок except
запускается, когда блок try
не срабатывает из-за исключения. Инструкции в этом блоке часто дают некоторый контекст того, что пошло не так внутри блока try
.
Если собираетесь перехватить ошибку как исключение, в блоке except
нужно обязательно указать тип этой ошибки. В приведенном выше сниппете место для указания типа ошибки обозначено плейсхолдером <error type>
.
except
можно использовать и без указания типа ошибки. Но лучше так не делать. При таком подходе не учитывается, что возникающие ошибки могут быть разных типов. То есть вы будете знать, что что-то пошло не так, но что именно произошло, какая была ошибка — вам будет не известно.
При попытке выполнить код внутри блока try
также существует вероятность возникновения нескольких ошибок.
Например, вы можете попытаться обратиться к элементу списка по индексу, выходящему за пределы допустимого диапазона, использовать неправильный ключ словаря и попробовать открыть несуществующий файл – и все это внутри одного блока try
.
В результате вы можете столкнуться с IndexError
, KeyError
и FileNotFoundError
. В таком случае нужно добавить столько блоков except
, сколько ошибок ожидается – по одному для каждого типа ошибки.
Блок else
Блок else
запускается только в том случае, если блок try
выполняется без ошибок. Это может быть полезно, когда нужно выполнить ещё какие-то действия после успешного выполнения блока try
. Например, после успешного открытия файла вы можете прочитать его содержимое.
Блок finally
Блок finally
выполняется всегда, независимо от того, что происходит в других блоках. Это полезно, когда вы хотите освободить ресурсы после выполнения определенного блока кода.
Примечание: блоки else
и finally
не являются обязательными. В большинстве случаев вы можете использовать только блок try
, чтобы что-то сделать, и перехватывать ошибки как исключения внутри блока except
.
[python_ad_block]
Итак, теперь давайте используем полученные знания для обработки исключений в Python. Приступим!
Обработка ZeroDivisionError
Рассмотрим функцию divide()
, показанную ниже. Она принимает два аргумента – num
и div
– и возвращает частное от операции деления num/div
.
def divide(num,div): return num/div
Вызов функции с разными аргументами возвращает ожидаемый результат:
res = divide(100,8) print(res) # Output # 12.5 res = divide(568,64) print(res) # Output # 8.875
Этот код работает нормально, пока вы не попробуете разделить число на ноль:
divide(27,0)
Вы видите, что программа выдает ошибку ZeroDivisionError
:
# Output --------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-19-932ea024ce43> in <module>() ----> 1 divide(27,0) <ipython-input-1-c98670fd7a12> in divide(num, div) 1 def divide(num,div): ----> 2 return num/div ZeroDivisionError: division by zero
Можно обработать деление на ноль как исключение, выполнив следующие действия:
- В блоке
try
поместите вызов функцииdivide()
. По сути, вы пытаетесь разделитьnum
наdiv
(try в переводе с английского — «пытаться», — прим. перев.). - В блоке
except
обработайте случай, когдаdiv
равен 0, как исключение. - В результате этих действий при делении на ноль больше не будет выбрасываться ZeroDivisionError. Вместо этого будет выводиться сообщение, информирующее пользователя, что он попытался делить на ноль.
Вот как все это выглядит в коде:
try: res = divide(num,div) print(res) except ZeroDivisionError: print("You tried to divide by zero :( ")
При корректных входных данных наш код по-прежнему работает великолепно:
divide(10,2) # Output # 5.0
Когда же пользователь попытается разделить на ноль, он получит уведомление о возникшем исключении. Таким образом, программа завершается корректно и без ошибок.
divide(10,0) # Output # You tried to divide by zero :(
Обработка TypeError
В этом разделе мы разберем, как использовать try
и except
для обработки TypeError
в Python.
Рассмотрим функцию add_10()
. Она принимает число в качестве аргумента, прибавляет к нему 10 и возвращает результат этого сложения.
def add_10(num): return num + 10
Вы можете вызвать функцию add_10()
с любым числом, и она будет работать нормально, как показано ниже:
result = add_10(89) print(result) # Output # 99
Теперь попробуйте вызвать функцию add_10()
, передав ей в качестве аргумента не число, а строку.
add_10 ("five")
Ваша программа вылетит со следующим сообщением об ошибке:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-15-9844e949c84e> in <module>() ----> 1 add_10("five") <ipython-input-13-2e506d74d919> in add_10(num) 1 def add_10(num): ----> 2 return num + 10 TypeError: can only concatenate str (not "int") to str
Сообщение об ошибке TypeError: can only concatenate str (not "int") to str
говорит о том, что можно сложить только две строки, а не добавить целое число к строке.
Обработаем TypeError:
- В блок try мы помещаем вызов функции
add_10()
с my_num в качестве аргумента. Если аргумент допустимого типа, исключений не возникнет. - В противном случае срабатывает блок
except
, в который мы помещаем вывод уведомления для пользователя о том, что аргумент имеет недопустимый тип.
Это показано ниже:
my_num = "five" try: result = add_10(my_num) print(result) except TypeError: print("The argument `num` should be a number")
Поскольку теперь вы обработали TypeError
как исключение, при передаче невалидного аргумента ошибка не возникает. Вместо нее выводится сообщение, что аргумент имеет недопустимый тип.
The argument `num` should be a number
Обработка IndexError
Если вам приходилось работать со списками или любыми другими итерируемыми объектами, вы, вероятно, сталкивались с IndexError
.
Это связано с тем, что часто бывает сложно отслеживать все изменения в итерациях. И вы можете попытаться получить доступ к элементу по невалидному индексу.
В этом примере список my_list
состоит из 4 элементов. Допустимые индексы — 0, 1, 2 и 3 и -1, -2, -3, -4, если вы используете отрицательную индексацию.
Поскольку 2 является допустимым индексом, вы видите, что элемент с этим индексом (C++
) распечатывается:
my_list = ["Python","C","C++","JavaScript"] print(my_list[2]) # Output # C++
Но если вы попытаетесь получить доступ к элементу по индексу, выходящему за пределы допустимого диапазона, вы столкнетесь с IndexError
:
print(my_list[4])
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-7-437bc6501dea> in <module>() 1 my_list = ["Python","C","C++","JavaScript"] ----> 2 print(my_list[4]) IndexError: list index out of range
Теперь вы уже знакомы с шаблоном, и вам не составит труда использовать try
и except
для обработки данной ошибки.
В приведенном ниже фрагменте кода мы пытаемся получить доступ к элементу по индексу search_idx
.
search_idx = 3 try: print(my_list[search_idx]) except IndexError: print("Sorry, the list index is out of range")
Здесь search_idx = 3
является допустимым индексом, поэтому в результате выводится соответствующий элемент — JavaScript
.
Если search_idx
находится за пределами допустимого диапазона индексов, блок except
перехватывает IndexError
как исключение, и больше нет длинных сообщений об ошибках.
search_idx = 4 try: print(my_list[search_idx]) except IndexError: print("Sorry, the list index is out of range")
Вместо этого отображается сообщение о том, что search_idx
находится вне допустимого диапазона индексов:
Sorry, the list index is out of range
Обработка KeyError
Вероятно, вы уже сталкивались с KeyError
при работе со словарями в Python.
Рассмотрим следующий пример, где у нас есть словарь my_dict
.
my_dict ={"key1":"value1","key2":"value2","key3":"value3"} search_key = "non-existent key" print(my_dict[search_key])
В словаре my_dict
есть 3 пары «ключ-значение»: key1:value1
, key2:value2
и key3:value3
.
Теперь попытаемся получить доступ к значению, соответствующему несуществующему ключу non-existent key
.
Как и ожидалось, мы получим KeyError
:
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-2-2a61d404be04> in <module>() 1 my_dict ={"key1":"value1","key2":"value2","key3":"value3"} 2 search_key = "non-existent key" ----> 3 my_dict[search_key] KeyError: 'non-existent key'
Вы можете обработать KeyError
почти так же, как и IndexError
.
- Пробуем получить доступ к значению, которое соответствует ключу, определенному
search_key
. - Если
search_key
— валидный ключ, мы распечатываем соответствующее значение. - Если ключ невалиден и возникает исключение — задействуется блок except, чтобы сообщить об этом пользователю.
Все это можно видеть в следующем коде:
try: print(my_dict[search_key]) except KeyError: print("Sorry, that's not a valid key!") # Output: # Sorry, that's not a valid key!
Если вы хотите предоставить дополнительный контекст, например имя невалидного ключа, это тоже можно сделать. Возможно, ключ оказался невалидным из-за ошибки в написании. Если вы укажете этот ключ в сообщении, это поможет пользователю исправить опечатку.
Вы можете сделать это, перехватив невалидный ключ как <error_msg>
и используя его в сообщении, которое печатается при возникновении исключения:
try: print(my_dict[search_key]) except KeyError as error_msg: print(f"Sorry,{error_msg} is not a valid key!")
Обратите внимание, что теперь в сообщении об ошибки указано также и имя несуществующего ключа:
Sorry, 'non-existent key' is not a valid key!
Обработка FileNotFoundError
При работе с файлами в Python часто возникает ошибка FileNotFoundError
.
В следующем примере мы попытаемся открыть файл my_file.txt, указав его путь в функции open()
. Мы хотим прочитать файл и вывести его содержимое.
Однако мы еще не создали этот файл в указанном месте.
my_file = open("/content/sample_data/my_file.txt") contents = my_file.read() print(contents)
Поэтому, попытавшись запустить приведенный выше фрагмент кода, мы получим FileNotFoundError
:
--------------------------------------------------------------------------- FileNotFoundError Traceback (most recent call last) <ipython-input-4-4873cac1b11a> in <module>() ----> 1 my_file = open("my_file.txt") FileNotFoundError: [Errno 2] No such file or directory: 'my_file.txt'
А с помощью try
и except
мы можем сделать следующее:
- Попробуем открыть файл в блоке
try
. - Обработаем
FileNotFoundError
в блокеexcept
, сообщив пользователю, что он попытался открыть несуществующий файл. - Если блок
try
завершается успешно и файл действительно существует, прочтем и распечатаем содержимое. - В блоке
finally
закроем файл, чтобы не терять ресурсы. Файл будет закрыт независимо от того, что происходило на этапах открытия и чтения.
try: my_file = open("/content/sample_data/my_file.txt") except FileNotFoundError: print(f"Sorry, the file does not exist") else: contents = my_file.read() print(contents) finally: my_file.close()
Обратите внимание: мы обработали ошибку как исключение, и программа завершает работу, отображая следующее сообщение:
Sorry, the file does not exist
Теперь рассмотрим случай, когда срабатывает блок else
. Файл my_file.txt теперь присутствует по указанному ранее пути.
Вот содержимое этого файла:
Теперь повторный запуск нашего кода работает должным образом.
На этот раз файл my_file.txt присутствует, поэтому запускается блок else
и содержимое распечатывается, как показано ниже:
Надеемся, теперь вы поняли, как обрабатывать исключения при работе с файлами.
Заключение
В этом руководстве мы рассмотрели, как обрабатывать исключения в Python с помощью try и except.
Также мы разобрали на примерах, какие типы исключений могут возникать и как при помощи except ловить наиболее распространенные ошибки.
Надеемся, вам понравился этот урок. Успехов в написании кода!
Перевод статьи «Python Try and Except Statements – How to Handle Exceptions in Python».