Python ошибка преобразования типов

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

Синтаксис обработки исключений

Прежде чем переходить к обсуждению того, почему обработка исключений так важна, и рассматривать встроенные в 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, а в stmt2if. Затем они выполняются 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 их обрабатывает.

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

Firstly, try / except are not functions, but statements.

To convert a string (or any other type that can be converted) to an integer in Python, simply call the int() built-in function. int() will raise a ValueError if it fails and you should catch this specifically:

In Python 2.x:

>>> for value in '12345', 67890, 3.14, 42L, 0b010101, 0xFE, 'Not convertible':
...     try:
...         print '%s as an int is %d' % (str(value), int(value))
...     except ValueError as ex:
...         print '"%s" cannot be converted to an int: %s' % (value, ex)
...
12345 as an int is 12345
67890 as an int is 67890
3.14 as an int is 3
42 as an int is 42
21 as an int is 21
254 as an int is 254
"Not convertible" cannot be converted to an int: invalid literal for int() with base 10: 'Not convertible'

In Python 3.x

the syntax has changed slightly:

>>> for value in '12345', 67890, 3.14, 42, 0b010101, 0xFE, 'Not convertible':
...     try:
...         print('%s as an int is %d' % (str(value), int(value)))
...     except ValueError as ex:
...         print('"%s" cannot be converted to an int: %s' % (value, ex))
...
12345 as an int is 12345
67890 as an int is 67890
3.14 as an int is 3
42 as an int is 42
21 as an int is 21
254 as an int is 254
"Not convertible" cannot be converted to an int: invalid literal for int() with base 10: 'Not convertible'

Содержание:развернуть

  • Как устроен механизм исключений
  • Как обрабатывать исключения в Python (try except)
  • As — сохраняет ошибку в переменную

  • Finally — выполняется всегда

  • Else — выполняется когда исключение не было вызвано

  • Несколько блоков except

  • Несколько типов исключений в одном блоке except

  • Raise — самостоятельный вызов исключений

  • Как пропустить ошибку

  • Исключения в lambda функциях
  • 20 типов встроенных исключений в Python
  • Как создать свой тип Exception

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

  • Синтаксические ошибки — возникают, когда написанное выражение не соответствует правилам языка (например, написана лишняя скобка);
  • Исключения — возникают во время выполнения программы (например, при делении на ноль).

Синтаксические ошибки исправить просто (если вы используете IDE, он их подсветит). А вот с исключениями всё немного сложнее — не всегда при написании программы можно сказать возникнет или нет в данном месте исключение. Чтобы приложение продолжило работу при возникновении проблем, такие ошибки нужно перехватывать и обрабатывать с помощью блока try/except.

Как устроен механизм исключений

В Python есть встроенные исключения, которые появляются после того как приложение находит ошибку. В этом случае текущий процесс временно приостанавливается и передает ошибку на уровень вверх до тех пор, пока она не будет обработано. Если ошибка не будет обработана, программа прекратит свою работу (а в консоли мы увидим Traceback с подробным описанием ошибки).

💁‍♂️ Пример: напишем скрипт, в котором функция ожидает число, а мы передаём сроку (это вызовет исключение «TypeError»):

def b(value):
print("-> b")
print(value + 1) # ошибка тут

def a(value):
print("-> a")
b(value)

a("10")

> -> a
> -> b
> Traceback (most recent call last):
> File "test.py", line 11, in <module>
> a("10")
> File "test.py", line 8, in a
> b(value)
> File "test.py", line 3, in b
> print(value + 1)
> TypeError: can only concatenate str (not "int") to str

В данном примере мы запускаем файл «test.py» (через консоль). Вызывается функция «a«, внутри которой вызывается функция «b«. Все работает хорошо до сточки print(value + 1). Тут интерпретатор понимает, что нельзя конкатенировать строку с числом, останавливает выполнение программы и вызывает исключение «TypeError».

Далее ошибка передается по цепочке в обратном направлении: «b» → «a» → «test.py«. Так как в данном примере мы не позаботились обработать эту ошибку, вся информация по ошибке отобразится в консоли в виде Traceback.

Traceback (трассировка) — это отчёт, содержащий вызовы функций, выполненные в определенный момент. Трассировка помогает узнать, что пошло не так и в каком месте это произошло.

Traceback лучше читать снизу вверх ↑

Пример Traceback в Python

В нашем примере Traceback содержится следующую информацию (читаем снизу вверх):

  1. TypeError — тип ошибки (означает, что операция не может быть выполнена с переменной этого типа);
  2. can only concatenate str (not "int") to str — подробное описание ошибки (конкатенировать можно только строку со строкой);
  3. Стек вызова функций (1-я линия — место, 2-я линия — код). В нашем примере видно, что в файле «test.py» на 11-й линии был вызов функции «a» со строковым аргументом «10». Далее был вызов функции «b». print(value + 1) это последнее, что было выполнено — тут и произошла ошибка.
  4. most recent call last — означает, что самый последний вызов будет отображаться последним в стеке (в нашем примере последним выполнился print(value + 1)).

В Python ошибку можно перехватить, обработать, и продолжить выполнение программы — для этого используется конструкция try ... except ....

Как обрабатывать исключения в Python (try except)

В Python исключения обрабатываются с помощью блоков try/except. Для этого операция, которая может вызвать исключение, помещается внутрь блока try. А код, который должен быть выполнен при возникновении ошибки, находится внутри except.

Например, вот как можно обработать ошибку деления на ноль:

try:
a = 7 / 0
except:
print('Ошибка! Деление на 0')

Здесь в блоке try находится код a = 7 / 0 — при попытке его выполнить возникнет исключение и выполнится код в блоке except (то есть будет выведено сообщение «Ошибка! Деление на 0»). После этого программа продолжит свое выполнение.

💭 PEP 8 рекомендует, по возможности, указывать конкретный тип исключения после ключевого слова except (чтобы перехватывать и обрабатывать конкретные исключения):

try:
a = 7 / 0
except ZeroDivisionError:
print('Ошибка! Деление на 0')

Однако если вы хотите перехватывать все исключения, которые сигнализируют об ошибках программы, используйте тип исключения Exception:

try:
a = 7 / 0
except Exception:
print('Любая ошибка!')

As — сохраняет ошибку в переменную

Перехваченная ошибка представляет собой объект класса, унаследованного от «BaseException». С помощью ключевого слова as можно записать этот объект в переменную, чтобы обратиться к нему внутри блока except:

try:
file = open('ok123.txt', 'r')
except FileNotFoundError as e:
print(e)

> [Errno 2] No such file or directory: 'ok123.txt'

В примере выше мы обращаемся к объекту класса «FileNotFoundError» (при выводе на экран через print отобразится строка с полным описанием ошибки).

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

import datetime

now = datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S")

try:
file = open('ok123.txt', 'r')
except FileNotFoundError as e:
print(f"{now} [FileNotFoundError]: {e.strerror}, filename: {e.filename}")

> 20-11-2021 18:42:01 [FileNotFoundError]: No such file or directory, filename: ok123.txt

Finally — выполняется всегда

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

Обычно try/except используется для перехвата исключений и восстановления нормальной работы приложения, а try/finally для того, чтобы гарантировать выполнение определенных действий (например, для закрытия внешних ресурсов, таких как ранее открытые файлы).

В следующем примере откроем файл и обратимся к несуществующей строке:

file = open('ok.txt', 'r')

try:
lines = file.readlines()
print(lines[5])
finally:
file.close()
if file.closed:
print("файл закрыт!")

> файл закрыт!
> Traceback (most recent call last):
> File "test.py", line 5, in <module>
> print(lines[5])
> IndexError: list index out of range

Даже после исключения «IndexError», сработал код в секции finally, который закрыл файл.

p.s. данный пример создан для демонстрации, в реальном проекте для работы с файлами лучше использовать менеджер контекста with.

Также можно использовать одновременно три блока try/except/finally. В этом случае:

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

def sum(a, b):
res = 0

try:
res = a + b
except TypeError:
res = int(a) + int(b)
finally:
print(f"a = {a}, b = {b}, res = {res}")

sum(1, "2")

> a = 1, b = 2, res = 3

Else — выполняется когда исключение не было вызвано

Иногда нужно выполнить определенные действия, когда код внутри блока try не вызвал исключения. Для этого используется блок else.

Допустим нужно вывести результат деления двух чисел и обработать исключения в случае попытки деления на ноль:

b = int(input('b = '))
c = int(input('c = '))
try:
a = b / c
except ZeroDivisionError:
print('Ошибка! Деление на 0')
else:
print(f"a = {a}")

> b = 10
> c = 1
> a = 10.0

В этом случае, если пользователь присвоит переменной «с» ноль, то появится исключение и будет выведено сообщение «‘Ошибка! Деление на 0′», а код внутри блока else выполняться не будет. Если ошибки не будет, то на экране появятся результаты деления.

Несколько блоков except

В программе может возникнуть несколько исключений, например:

  1. Ошибка преобразования введенных значений к типу float («ValueError»);
  2. Деление на ноль («ZeroDivisionError»).

В Python, чтобы по-разному обрабатывать разные типы ошибок, создают несколько блоков except:

try:
b = float(input('b = '))
c = float(input('c = '))
a = b / c
except ZeroDivisionError:
print('Ошибка! Деление на 0')
except ValueError:
print('Число введено неверно')
else:
print(f"a = {a}")

> b = 10
> c = 0
> Ошибка! Деление на 0

> b = 10
> c = питон
> Число введено неверно

Теперь для разных типов ошибок есть свой обработчик.

Несколько типов исключений в одном блоке except

Можно также обрабатывать в одном блоке except сразу несколько исключений. Для этого они записываются в круглых скобках, через запятую сразу после ключевого слова except. Чтобы обработать сообщения «ZeroDivisionError» и «ValueError» в одном блоке записываем их следующим образом:

try:
b = float(input('b = '))
c = float(input('c = '))
a = b / c
except (ZeroDivisionError, ValueError) as er:
print(er)
else:
print('a = ', a)

При этом переменной er присваивается объект того исключения, которое было вызвано. В результате на экран выводятся сведения о конкретной ошибке.

Raise — самостоятельный вызов исключений

Исключения можно генерировать самостоятельно — для этого нужно запустить оператор raise.

min = 100
if min > 10:
raise Exception('min must be less than 10')

> Traceback (most recent call last):
> File "test.py", line 3, in <module>
> raise Exception('min value must be less than 10')
> Exception: min must be less than 10

Перехватываются такие сообщения точно так же, как и остальные:

min = 100

try:
if min > 10:
raise Exception('min must be less than 10')
except Exception:
print('Моя ошибка')

> Моя ошибка

Кроме того, ошибку можно обработать в блоке except и пробросить дальше (вверх по стеку) с помощью raise:

min = 100

try:
if min > 10:
raise Exception('min must be less than 10')
except Exception:
print('Моя ошибка')
raise

> Моя ошибка
> Traceback (most recent call last):
> File "test.py", line 5, in <module>
> raise Exception('min must be less than 10')
> Exception: min must be less than 10

Как пропустить ошибку

Иногда ошибку обрабатывать не нужно. В этом случае ее можно пропустить с помощью pass:

try:
a = 7 / 0
except ZeroDivisionError:
pass

Исключения в lambda функциях

Обрабатывать исключения внутри lambda функций нельзя (так как lambda записывается в виде одного выражения). В этом случае нужно использовать именованную функцию.

20 типов встроенных исключений в Python

Иерархия классов для встроенных исключений в Python выглядит так:

BaseException
SystemExit
KeyboardInterrupt
GeneratorExit
Exception
ArithmeticError
AssertionError
...
...
...
ValueError
Warning

Все исключения в Python наследуются от базового BaseException:

  • SystemExit — системное исключение, вызываемое функцией sys.exit() во время выхода из приложения;
  • KeyboardInterrupt — возникает при завершении программы пользователем (чаще всего при нажатии клавиш Ctrl+C);
  • GeneratorExit — вызывается методом close объекта generator;
  • Exception — исключения, которые можно и нужно обрабатывать (предыдущие были системными и их трогать не рекомендуется).

От Exception наследуются:

1 StopIteration — вызывается функцией next в том случае если в итераторе закончились элементы;

2 ArithmeticError — ошибки, возникающие при вычислении, бывают следующие типы:

  • FloatingPointError — ошибки при выполнении вычислений с плавающей точкой (встречаются редко);
  • OverflowError — результат вычислений большой для текущего представления (не появляется при операциях с целыми числами, но может появиться в некоторых других случаях);
  • ZeroDivisionError — возникает при попытке деления на ноль.

3 AssertionError — выражение, используемое в функции assert неверно;

4 AttributeError — у объекта отсутствует нужный атрибут;

5 BufferError — операция, для выполнения которой требуется буфер, не выполнена;

6 EOFError — ошибка чтения из файла;

7 ImportError — ошибка импортирования модуля;

8 LookupError — неверный индекс, делится на два типа:

  • IndexError — индекс выходит за пределы диапазона элементов;
  • KeyError — индекс отсутствует (для словарей, множеств и подобных объектов);

9 MemoryError — память переполнена;

10 NameError — отсутствует переменная с данным именем;

11 OSError — исключения, генерируемые операционной системой:

  • ChildProcessError — ошибки, связанные с выполнением дочернего процесса;
  • ConnectionError — исключения связанные с подключениями (BrokenPipeError, ConnectionResetError, ConnectionRefusedError, ConnectionAbortedError);
  • FileExistsError — возникает при попытке создания уже существующего файла или директории;
  • FileNotFoundError — генерируется при попытке обращения к несуществующему файлу;
  • InterruptedError — возникает в том случае если системный вызов был прерван внешним сигналом;
  • IsADirectoryError — программа обращается к файлу, а это директория;
  • NotADirectoryError — приложение обращается к директории, а это файл;
  • PermissionError — прав доступа недостаточно для выполнения операции;
  • ProcessLookupError — процесс, к которому обращается приложение не запущен или отсутствует;
  • TimeoutError — время ожидания истекло;

12 ReferenceError — попытка доступа к объекту с помощью слабой ссылки, когда объект не существует;

13 RuntimeError — генерируется в случае, когда исключение не может быть классифицировано или не подпадает под любую другую категорию;

14 NotImplementedError — абстрактные методы класса нуждаются в переопределении;

15 SyntaxError — ошибка синтаксиса;

16 SystemError — сигнализирует о внутренне ошибке;

17 TypeError — операция не может быть выполнена с переменной этого типа;

18 ValueError — возникает когда в функцию передается объект правильного типа, но имеющий некорректное значение;

19 UnicodeError — исключение связанное с кодирование текста в unicode, бывает трех видов:

  • UnicodeEncodeError — ошибка кодирования;
  • UnicodeDecodeError — ошибка декодирования;
  • UnicodeTranslateError — ошибка перевода unicode.

20 Warning — предупреждение, некритическая ошибка.

💭 Посмотреть всю цепочку наследования конкретного типа исключения можно с помощью модуля inspect:

import inspect

print(inspect.getmro(TimeoutError))

> (<class 'TimeoutError'>, <class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)

📄 Подробное описание всех классов встроенных исключений в Python смотрите в официальной документации.

Как создать свой тип Exception

В Python можно создавать свои исключения. При этом есть одно обязательное условие: они должны быть потомками класса Exception:

class MyError(Exception):
def __init__(self, text):
self.txt = text

try:
raise MyError('Моя ошибка')
except MyError as er:
print(er)

> Моя ошибка


С помощью try/except контролируются и обрабатываются ошибки в приложении. Это особенно актуально для критически важных частей программы, где любые «падения» недопустимы (или могут привести к негативным последствиям). Например, если программа работает как «демон», падение приведет к полной остановке её работы. Или, например, при временном сбое соединения с базой данных, программа также прервёт своё выполнение (хотя можно было отловить ошибку и попробовать соединиться в БД заново).

Вместе с try/except можно использовать дополнительные блоки. Если использовать все блоки описанные в статье, то код будет выглядеть так:

try:
# попробуем что-то сделать
except (ZeroDivisionError, ValueError) as e:
# обрабатываем исключения типа ZeroDivisionError или ValueError
except Exception as e:
# исключение не ZeroDivisionError и не ValueError
# поэтому обрабатываем исключение общего типа (унаследованное от Exception)
# сюда не сходят исключения типа GeneratorExit, KeyboardInterrupt, SystemExit
else:
# этот блок выполняется, если нет исключений
# если в этом блоке сделать return, он не будет вызван, пока не выполнился блок finally
finally:
# этот блок выполняется всегда, даже если нет исключений else будет проигнорирован
# если в этом блоке сделать return, то return в блоке

Подробнее о работе с исключениями в Python можно ознакомиться в официальной документации.

I’ve the following dataframe

df1 = df[['tripduration','starttime','stoptime','start station name','end station name','bikeid','usertype','birth year','gender']]
print(df1.head(2))

which prints the following

tripduration            starttime             stoptime start station name  
0           364  2017-09-01 00:02:01  2017-09-01 00:08:05     Exchange Place   
1           357  2017-09-01 00:08:12  2017-09-01 00:14:09          Warren St   

   end station name  bikeid    usertype  birth year  gender  
0  Marin Light Rail   29670  Subscriber      1989.0       1  
1      Newport Pkwy   26163  Subscriber      1980.0       1

I am using the following code to convert «birth year» column type from float to int.

df1[['birth year']] = df1[['birth year']].astype(int)
print df1.head(2)

But I get the following error. How to fix this?

ValueErrorTraceback (most recent call last)
<ipython-input-25-0fe766e4d4a7> in <module>()
----> 1 df1[['birth year']] = df1[['birth year']].astype(int)
      2 print df1.head(2)
      3 __zeppelin__._displayhook()

/usr/miniconda2/lib/python2.7/site-packages/pandas/util/_decorators.pyc in wrapper(*args, **kwargs)
    116                 else:
    117                     kwargs[new_arg_name] = new_arg_value
--> 118             return func(*args, **kwargs)
    119         return wrapper
    120     return _deprecate_kwarg

/usr/miniconda2/lib/python2.7/site-packages/pandas/core/generic.pyc in astype(self, dtype, copy, errors, **kwargs)
   4002         # else, only a single dtype is given
   4003         new_data = self._data.astype(dtype=dtype, copy=copy, errors=errors,
-> 4004                                      **kwargs)
   4005         return self._constructor(new_data).__finalize__(self)
   4006 

/usr/miniconda2/lib/python2.7/site-packages/pandas/core/internals.pyc in astype(self, dtype, **kwargs)
   3460 
   3461     def astype(self, dtype, **kwargs):
-> 3462         return self.apply('astype', dtype=dtype, **kwargs)
   3463 
   3464     def convert(self, **kwargs):

/usr/miniconda2/lib/python2.7/site-packages/pandas/core/internals.pyc in apply(self, f, axes, filter, do_integrity_check, consolidate, **kwargs)
   3327 
   3328             kwargs['mgr'] = self
-> 3329             applied = getattr(b, f)(**kwargs)
   3330             result_blocks = _extend_blocks(applied, result_blocks)
   3331 

/usr/miniconda2/lib/python2.7/site-packages/pandas/core/internals.pyc in astype(self, dtype, copy, errors, values, **kwargs)
    542     def astype(self, dtype, copy=False, errors='raise', values=None, **kwargs):
    543         return self._astype(dtype, copy=copy, errors=errors, values=values,
--> 544                             **kwargs)
    545 
    546     def _astype(self, dtype, copy=False, errors='raise', values=None,

/usr/miniconda2/lib/python2.7/site-packages/pandas/core/internals.pyc in _astype(self, dtype, copy, errors, values, klass, mgr, **kwargs)
    623 
    624                 # _astype_nansafe works fine with 1-d only
--> 625                 values = astype_nansafe(values.ravel(), dtype, copy=True)
    626                 values = values.reshape(self.shape)
    627 

/usr/miniconda2/lib/python2.7/site-packages/pandas/core/dtypes/cast.pyc in astype_nansafe(arr, dtype, copy)
    685 
    686         if not np.isfinite(arr).all():
--> 687             raise ValueError('Cannot convert non-finite values (NA or inf) to '
    688                              'integer')
    689 

ValueError: Cannot convert non-finite values (NA or inf) to integer

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

Синтаксис обработки исключений

Прежде чем переходить к обсуждению того, почему обработка исключений так важна, и рассматривать встроенные в 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, а в stmt2if. Затем они выполняются 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 их обрабатывает.

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

TraceBack: ошибки в Python

В процессе обучения, мы часто сталкиваемся с трекбеком, которым Python реагирует на возникающие ошибки. Это может быть не корректный ввод команды, неверное преобразование типов, обращение к несуществующему ключу или индексу, попытка совершить какое-то не предусмотренное действие с объектами, обратиться к несуществующей функции или методу, неправильно передать аргументы в функцию или метод… Python, встречая ошибку в синтаксисе или семантике кода, генерирует Traceback, в котором сообщает краткую информацию о том, в каком файле и в какой строке было возбуждено исключение(ошибка) и тип(название) данного исключения. Давайте посмотрим на некоторые исключения в Python:

>>> print var # Попытка вывести на экран, содержимое несуществующей переменной

Traceback (most recent call last):

  File «

«, line 1, in

NameError: name ‘var’ is not defined

>>>

Python вернул нам трекбек, с типом «NameError». Переменной с таким названием не существует. Любое обращение к несуществующей переменной, будет оканчиваться подобным исключением.

>>> a = ‘Hello’

>>> b = 2

>>> a + b

Traceback (most recent call last):

  File «

«, line 1, in

TypeError: cannot concatenate ‘str’ and ‘int’ objects

>>>

Тут мы попытались сплюсовать 2 значения — строчное и численное, на что Python выдал нам исключение «TypeError» — ошибка с типами, Не возможно совершить конгатенацию с строчным(str) и  целочисленным(int) типами данных.

>>> int(‘hello’) # Попытка приведения слова к числу

Traceback (most recent call last):

  File «

«, line 1, in

ValueError: invalid literal for int() with base 10: ‘hello’

>>>

Тут мы попытались привести к целочисленному типу строку, которая содержит слово и Python вернул нам трекбек типа «ValueError» — ошибка содержимого, ошибочный литерал строки, который не может быть приведен к int() и должен содержать в себе число в десятичной(привычной нам) системе счисления.

>>> 5/0 # Попытка деления на 0

Traceback (most recent call last):

  File «

«, line 1, in

ZeroDivisionError: integer division or modulo by zero

>>>

Классическая ошибка в математике — попытка деления на 0, которая возбуждает исключение типа «ZeroDivisionError» — Невозможность делить на 0.

>>> ‘test’.len()

Traceback (most recent call last):

  File «

«, line 1, in

AttributeError: ‘str’ object has no attribute ‘len’

>>>

Тут мы попытались вызвать несуществующий метод в объекте строки, на что Python отреагировал трекбеком типа «AttributeError» — ошибка атрибута, такого атрибута(метода) в данном объекте не предусмотрено.

Мы рассмотрели некоторые типы исключений, которые возвращает нам Python. Естественно их несколько больше, причем в процессе обучения, вы научитесь создавать свои типы исключений, которые будут носить свои названия.

Если в процессе выполнения вашего кода Python вернет трекбек, данный процесс прервется и не будет выполнен. Чтобы избежать подобной ситуации, мы можем отлавливать исключения и ориентируясь по их типу, выполнять то или иное действие, которое поможет избежать ошибки. Сама по себе ошибка будет, но вместо того, чтобы Python оборвал процесс выполнения кода, мы попросим его выполнить какие-то действия. Для этого существует конструкция try except. После оператора try, мы помещаем блок кода, в котором может возникнуть исключение и при помощи оператора except, указываем, какие действия нам необходимо выполнить, при возбуждении исключения того или иного типа.

try except

После оператора try, мы пишем блок кода, который гипотетический может вызвать ошибку, а может и не гипотетически, Т.Е. Иногда мы будем сознательно создавать и обрабатывать некоторые исключения, Т.К. Это просто будет удобно. Оператор except может отлавливать ошибки двумя способами. Если мы укажем:

try:

    блок кода, где возникнет исключение

except:

    блок кода, который будет выполняться в случае возникновения исключения

В данной структуре, оператор except, отловит любую ошибку, которая может появиться в блоке кода после try. Но ведь в одном блоке кода может возникнуть несколько ошибок. Конечно, некоторые из ошибок мы можем физически разделить на несколько блоков при условии, что эти ошибки могут возникнуть в нескольких отдельных строках, а что делать, если одна строка может возбудить несколько исключений? Это достаточно легко представить. Кпримеру в одной строке может выполняться ошибочное преобразование типов, обращение к несуществующему ключу словаря, обращение к неверному индексу списка, вызов несуществующего метода какого-то объекта… Разве этого недостаточно? Естественно стоит утверждать, что таких ошибок программист должен избежать, но иногда их избежать просто невозможно, а иногда программист сам выстраивает такую логику, чтобы воспользовавшись исключениями, построить структуру своего кода. Чтобы нам отловить какой-то конкретный трекбек, после оператора except, нужно указать тип(название) исключения, кпримеру Type Error — ошибка преобразования типов. После try, мы можем указать необходимое количество except, каждй из которых будет отлавливать свою ошибку и выполнять соответствующий для них код. Давайте посмотрим на несколько примеров:

>>> try:

…     int(‘Hello’) # Попытка преобразовать слово в число

… except:

…     print u»Ошибка преобразования типов!»

Ошибка преобразования типов!

>>>

Как видно, вместо трекбека, Python выполнил код после оператора except:

>>> d = {}

>>> d[‘one’]

Traceback (most recent call last):

  File «

«, line 1, in

KeyError: ‘one’

>>> try:

…     d[‘one’]

… except KeyError:

…     print u»Ошибка, было обращение к несуществующему ключу в словаре»

Ошибка, было обращение к несуществующему ключу в словаре

>>>

>>> a = ’10’

>>> b = ‘0’

>>> try:

…     int(a)/int(b)

… except ZeroDivisionError:

…     print u»Ошибка! Попытка деления на 0″

… except TypeError:

…     print U»Ошибка преобразования типов!»

Ошибка! Попытка деления на 0

>>>

>>> a = ‘Hello’

>>> a

‘Hello’

>>> b

‘0’

>>> try:

…     int(a)/int(b)

… except ZeroDivisionError:

…     print u»Ошибка! Попытка деления на 0″

… except ValueError:

…     print U»Ошибка преобразования типов!»

Ошибка преобразования типов!

>>>

Если помимо ошибок, которые вы можете предусмотреть, может возникнуть еще какая-то. Вконце предусмотренных except, которые будут отлавливать строго определенные исключения, можно написать except без уточнения типа исключения, который, взависимости от логики вашего кода, может обработать непредсказуемую ошибку.

else

Да-да, в конструкции try except, тоже есть необязательная часть else. Если вспомнить все, что мы знаем о операторе else в конструкциях if else, while else, for else, мы можем предположить, что необязательная часть else, будет выполнена в том случае, если в блоке кода после try, исключение так и не будет возбуждено. Т.Е. Если в блоке кода после try, все пройдет гладко и Python в течении выполнения блока кода ниразу не попытается вернуть трекбек, после выполнения блока кода заложенного после try, будет выполнен блок кода после else. Конструкция следующая:

try:

    блок кода

except:

    блок кода

else:

    блок кода

Именно в таком порядке:

>>> try:

…     10/0

… except ZeroDivisionError:

…     print u»Попытка деления на 0″

… else:

…     print u»Ошибок небыло»

Попытка деления на 0

>>> try:

…     10/2

… except ZeroDivisionError:

…     print u»Попытка деления на 0″

… else:

…     print u»Ошибок небыло»

Ошибок небыло

>>>

finally

В конструкции try except, предусмотрен еще один необязательный оператор finally, блок кода после которого будет выполнен в любом случае, Т.Е. Неважно возникнет ли исключение в блоке после try или нет, отработает ли else, если таковой будет в конструкции, блок кода после finally будет выполнен при любых обстоятельствах. Конструкция выглядит следующим образом:

try:

    блок кода

except:

    блок кода

else: (Если таковой необходим в конструкции)

    блок кода

finally:

    блок кода

Зачем нам нужен отдельный блок кода, который будет выполнен при любых условиях? Пожалуй самым ярким примером будет случай, если нам нужно будет выполнить что-то в цикле for или while, при условии, что они будут обрываться оператором continue или break, а мы помним, что при использовании этих операторов, часть кода которая находится после них, выполнена не будет. Но если break или continue будут использованы в конструкции try except, которая будет иметь часть finally, код в блоке finally будет выполнен даже при условии прерывания цикла:

>>> a = 5

>>> b = 10

>>> while True:

…     try:

…             c = b / a

…             a = a -1

…     except:

…             print u»Ошибка!»

…             break

…     finally:

…             print u»Делим на «,a,u»результат «,c

Делим на  4 результат  2

Делим на  3 результат  2

Делим на  2 результат  3

Делим на  1 результат  5

Делим на  0 результат  10

Ошибка!

Делим на  0 результат  10

>>>

Как видим, блок кода после finally сообщал нам результат все время выполнения цикла и сообщил его даже тогда, когда была произведена попытка деления на 0 и цикл был прерван оператором break.

In this article we will discuss how to fix the value error – cannot convert float NaN to integer in Python.

In Python, NaN stands for Not a Number. This error will occur when we are converting the dataframe column of the float type that contains NaN values to an integer.

Let’s see the error and explore the methods to deal with it.

Dataset in use:

Let’s check the error when converting from float type (marks column) to integer type. We can convert by using astype() function

Example: Depicting the error

Python3

import pandas

import numpy

dataframe = pandas.DataFrame({'name': ['sireesha', 'gnanesh',

                                       'sridevi', 'vijay', 'sreemukhi'],

                              'marks': [90.3, numpy.nan, 67.8, 89, numpy.nan]})

dataframe['marks'].astype(int)

Output:

ValueError: Cannot convert non-finite values (NA or inf) to integer

Because the NaN values are not possible to convert the dataframe. So in order to fix this issue, we have to remove NaN values

Method 1: Drop rows with NaN values

Here we are going to remove NaN values from the dataframe column by using dropna() function. This function will remove the rows that contain NaN values.

Syntax:

dataframe.dropna()

Example: Dealing with error 

Python3

import pandas

import numpy

dataframe = pandas.DataFrame({'name': ['sireesha', 'gnanesh',

                                       'sridevi', 'vijay',

                                       'sreemukhi'],

                              'marks': [90.3, numpy.nan, 67.8, 89, numpy.nan]})

print(dataframe['marks'] .dtype)

dataframe = dataframe.dropna()

print(dataframe)

dataframe['marks'] = dataframe['marks'].astype(int)

dataframe['marks'] .dtype

Output:

Method 2: Replace NaN values with 0

We can replace NaN values with 0 to get rid of NaN values. This is done by using fillna() function. This function will check the NaN values in the dataframe columns and fill the given value.

Syntax:

dataframe.fillna(0)

Example: Dealing with the error

Python3

import pandas

import numpy

dataframe = pandas.DataFrame({'name': ['sireesha', 'gnanesh',

                                       'sridevi', 'vijay',

                                       'sreemukhi'],

                              'marks': [90.3, numpy.nan, 67.8, 89, numpy.nan]})

print(dataframe['marks'] .dtype)

dataframe = dataframe.fillna(0)

print(dataframe)

dataframe['marks'] = dataframe['marks'].astype(int)

dataframe['marks'] .dtype

Output:

Method 3: Using numpy.nan_to_num()

Here we are using NumPy to convert NaN values to 0 numbers.

Syntax:

numpy.nan_to_num(numpy.nal)

Example: Dealing with the error

Python3

import numpy

data = numpy.nan

print(data)

final = numpy.nan_to_num(data)

final

Output:

nan
0.0

Method 4: Use Nullable 

We can create nan value as NaN, this does not create any error while converting float to integer.

Syntax:

numpy.NaN

Example: Dealing with the error

Python3

import pandas

import numpy

dataframe = pandas.DataFrame({'name': ['sireesha', 'gnanesh',

                                       'sridevi', 'vijay',

                                       'sreemukhi'],

                              'marks': [90.3, numpy.NaN, 67.8, 89, numpy.NaN]})

print(dataframe['marks'] .dtype)

dataframe = dataframe.fillna(0)

print(dataframe)

dataframe['marks'] = dataframe['marks'].astype(int)

dataframe['marks'] .dtype

Output:

float64
        name  marks
0   sireesha   90.3
1    gnanesh    0.0
2    sridevi   67.8
3      vijay   89.0
4  sreemukhi    0.0
dtype('int64')

In this article we will discuss how to fix the value error – cannot convert float NaN to integer in Python.

In Python, NaN stands for Not a Number. This error will occur when we are converting the dataframe column of the float type that contains NaN values to an integer.

Let’s see the error and explore the methods to deal with it.

Dataset in use:

Let’s check the error when converting from float type (marks column) to integer type. We can convert by using astype() function

Example: Depicting the error

Python3

import pandas

import numpy

dataframe = pandas.DataFrame({'name': ['sireesha', 'gnanesh',

                                       'sridevi', 'vijay', 'sreemukhi'],

                              'marks': [90.3, numpy.nan, 67.8, 89, numpy.nan]})

dataframe['marks'].astype(int)

Output:

ValueError: Cannot convert non-finite values (NA or inf) to integer

Because the NaN values are not possible to convert the dataframe. So in order to fix this issue, we have to remove NaN values

Method 1: Drop rows with NaN values

Here we are going to remove NaN values from the dataframe column by using dropna() function. This function will remove the rows that contain NaN values.

Syntax:

dataframe.dropna()

Example: Dealing with error 

Python3

import pandas

import numpy

dataframe = pandas.DataFrame({'name': ['sireesha', 'gnanesh',

                                       'sridevi', 'vijay',

                                       'sreemukhi'],

                              'marks': [90.3, numpy.nan, 67.8, 89, numpy.nan]})

print(dataframe['marks'] .dtype)

dataframe = dataframe.dropna()

print(dataframe)

dataframe['marks'] = dataframe['marks'].astype(int)

dataframe['marks'] .dtype

Output:

Method 2: Replace NaN values with 0

We can replace NaN values with 0 to get rid of NaN values. This is done by using fillna() function. This function will check the NaN values in the dataframe columns and fill the given value.

Syntax:

dataframe.fillna(0)

Example: Dealing with the error

Python3

import pandas

import numpy

dataframe = pandas.DataFrame({'name': ['sireesha', 'gnanesh',

                                       'sridevi', 'vijay',

                                       'sreemukhi'],

                              'marks': [90.3, numpy.nan, 67.8, 89, numpy.nan]})

print(dataframe['marks'] .dtype)

dataframe = dataframe.fillna(0)

print(dataframe)

dataframe['marks'] = dataframe['marks'].astype(int)

dataframe['marks'] .dtype

Output:

Method 3: Using numpy.nan_to_num()

Here we are using NumPy to convert NaN values to 0 numbers.

Syntax:

numpy.nan_to_num(numpy.nal)

Example: Dealing with the error

Python3

import numpy

data = numpy.nan

print(data)

final = numpy.nan_to_num(data)

final

Output:

nan
0.0

Method 4: Use Nullable 

We can create nan value as NaN, this does not create any error while converting float to integer.

Syntax:

numpy.NaN

Example: Dealing with the error

Python3

import pandas

import numpy

dataframe = pandas.DataFrame({'name': ['sireesha', 'gnanesh',

                                       'sridevi', 'vijay',

                                       'sreemukhi'],

                              'marks': [90.3, numpy.NaN, 67.8, 89, numpy.NaN]})

print(dataframe['marks'] .dtype)

dataframe = dataframe.fillna(0)

print(dataframe)

dataframe['marks'] = dataframe['marks'].astype(int)

dataframe['marks'] .dtype

Output:

float64
        name  marks
0   sireesha   90.3
1    gnanesh    0.0
2    sridevi   67.8
3      vijay   89.0
4  sreemukhi    0.0
dtype('int64')

Содержание:развернуть

  • Как устроен механизм исключений
  • Как обрабатывать исключения в Python (try except)
  • As — сохраняет ошибку в переменную

  • Finally — выполняется всегда

  • Else — выполняется когда исключение не было вызвано

  • Несколько блоков except

  • Несколько типов исключений в одном блоке except

  • Raise — самостоятельный вызов исключений

  • Как пропустить ошибку

  • Исключения в lambda функциях
  • 20 типов встроенных исключений в Python
  • Как создать свой тип Exception

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

  • Синтаксические ошибки — возникают, когда написанное выражение не соответствует правилам языка (например, написана лишняя скобка);
  • Исключения — возникают во время выполнения программы (например, при делении на ноль).

Синтаксические ошибки исправить просто (если вы используете IDE, он их подсветит). А вот с исключениями всё немного сложнее — не всегда при написании программы можно сказать возникнет или нет в данном месте исключение. Чтобы приложение продолжило работу при возникновении проблем, такие ошибки нужно перехватывать и обрабатывать с помощью блока try/except.

Как устроен механизм исключений

В Python есть встроенные исключения, которые появляются после того как приложение находит ошибку. В этом случае текущий процесс временно приостанавливается и передает ошибку на уровень вверх до тех пор, пока она не будет обработано. Если ошибка не будет обработана, программа прекратит свою работу (а в консоли мы увидим Traceback с подробным описанием ошибки).

💁‍♂️ Пример: напишем скрипт, в котором функция ожидает число, а мы передаём сроку (это вызовет исключение «TypeError»):

def b(value):
print("-> b")
print(value + 1) # ошибка тут

def a(value):
print("-> a")
b(value)

a("10")

> -> a
> -> b
> Traceback (most recent call last):
> File "test.py", line 11, in <module>
> a("10")
> File "test.py", line 8, in a
> b(value)
> File "test.py", line 3, in b
> print(value + 1)
> TypeError: can only concatenate str (not "int") to str

В данном примере мы запускаем файл «test.py» (через консоль). Вызывается функция «a«, внутри которой вызывается функция «b«. Все работает хорошо до сточки print(value + 1). Тут интерпретатор понимает, что нельзя конкатенировать строку с числом, останавливает выполнение программы и вызывает исключение «TypeError».

Далее ошибка передается по цепочке в обратном направлении: «b» → «a» → «test.py«. Так как в данном примере мы не позаботились обработать эту ошибку, вся информация по ошибке отобразится в консоли в виде Traceback.

Traceback (трассировка) — это отчёт, содержащий вызовы функций, выполненные в определенный момент. Трассировка помогает узнать, что пошло не так и в каком месте это произошло.

Traceback лучше читать снизу вверх ↑

Пример Traceback в Python

В нашем примере Traceback содержится следующую информацию (читаем снизу вверх):

  1. TypeError — тип ошибки (означает, что операция не может быть выполнена с переменной этого типа);
  2. can only concatenate str (not "int") to str — подробное описание ошибки (конкатенировать можно только строку со строкой);
  3. Стек вызова функций (1-я линия — место, 2-я линия — код). В нашем примере видно, что в файле «test.py» на 11-й линии был вызов функции «a» со строковым аргументом «10». Далее был вызов функции «b». print(value + 1) это последнее, что было выполнено — тут и произошла ошибка.
  4. most recent call last — означает, что самый последний вызов будет отображаться последним в стеке (в нашем примере последним выполнился print(value + 1)).

В Python ошибку можно перехватить, обработать, и продолжить выполнение программы — для этого используется конструкция try ... except ....

Как обрабатывать исключения в Python (try except)

В Python исключения обрабатываются с помощью блоков try/except. Для этого операция, которая может вызвать исключение, помещается внутрь блока try. А код, который должен быть выполнен при возникновении ошибки, находится внутри except.

Например, вот как можно обработать ошибку деления на ноль:

try:
a = 7 / 0
except:
print('Ошибка! Деление на 0')

Здесь в блоке try находится код a = 7 / 0 — при попытке его выполнить возникнет исключение и выполнится код в блоке except (то есть будет выведено сообщение «Ошибка! Деление на 0»). После этого программа продолжит свое выполнение.

💭 PEP 8 рекомендует, по возможности, указывать конкретный тип исключения после ключевого слова except (чтобы перехватывать и обрабатывать конкретные исключения):

try:
a = 7 / 0
except ZeroDivisionError:
print('Ошибка! Деление на 0')

Однако если вы хотите перехватывать все исключения, которые сигнализируют об ошибках программы, используйте тип исключения Exception:

try:
a = 7 / 0
except Exception:
print('Любая ошибка!')

As — сохраняет ошибку в переменную

Перехваченная ошибка представляет собой объект класса, унаследованного от «BaseException». С помощью ключевого слова as можно записать этот объект в переменную, чтобы обратиться к нему внутри блока except:

try:
file = open('ok123.txt', 'r')
except FileNotFoundError as e:
print(e)

> [Errno 2] No such file or directory: 'ok123.txt'

В примере выше мы обращаемся к объекту класса «FileNotFoundError» (при выводе на экран через print отобразится строка с полным описанием ошибки).

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

import datetime

now = datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S")

try:
file = open('ok123.txt', 'r')
except FileNotFoundError as e:
print(f"{now} [FileNotFoundError]: {e.strerror}, filename: {e.filename}")

> 20-11-2021 18:42:01 [FileNotFoundError]: No such file or directory, filename: ok123.txt

Finally — выполняется всегда

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

Обычно try/except используется для перехвата исключений и восстановления нормальной работы приложения, а try/finally для того, чтобы гарантировать выполнение определенных действий (например, для закрытия внешних ресурсов, таких как ранее открытые файлы).

В следующем примере откроем файл и обратимся к несуществующей строке:

file = open('ok.txt', 'r')

try:
lines = file.readlines()
print(lines[5])
finally:
file.close()
if file.closed:
print("файл закрыт!")

> файл закрыт!
> Traceback (most recent call last):
> File "test.py", line 5, in <module>
> print(lines[5])
> IndexError: list index out of range

Даже после исключения «IndexError», сработал код в секции finally, который закрыл файл.

p.s. данный пример создан для демонстрации, в реальном проекте для работы с файлами лучше использовать менеджер контекста with.

Также можно использовать одновременно три блока try/except/finally. В этом случае:

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

def sum(a, b):
res = 0

try:
res = a + b
except TypeError:
res = int(a) + int(b)
finally:
print(f"a = {a}, b = {b}, res = {res}")

sum(1, "2")

> a = 1, b = 2, res = 3

Else — выполняется когда исключение не было вызвано

Иногда нужно выполнить определенные действия, когда код внутри блока try не вызвал исключения. Для этого используется блок else.

Допустим нужно вывести результат деления двух чисел и обработать исключения в случае попытки деления на ноль:

b = int(input('b = '))
c = int(input('c = '))
try:
a = b / c
except ZeroDivisionError:
print('Ошибка! Деление на 0')
else:
print(f"a = {a}")

> b = 10
> c = 1
> a = 10.0

В этом случае, если пользователь присвоит переменной «с» ноль, то появится исключение и будет выведено сообщение «‘Ошибка! Деление на 0′», а код внутри блока else выполняться не будет. Если ошибки не будет, то на экране появятся результаты деления.

Несколько блоков except

В программе может возникнуть несколько исключений, например:

  1. Ошибка преобразования введенных значений к типу float («ValueError»);
  2. Деление на ноль («ZeroDivisionError»).

В Python, чтобы по-разному обрабатывать разные типы ошибок, создают несколько блоков except:

try:
b = float(input('b = '))
c = float(input('c = '))
a = b / c
except ZeroDivisionError:
print('Ошибка! Деление на 0')
except ValueError:
print('Число введено неверно')
else:
print(f"a = {a}")

> b = 10
> c = 0
> Ошибка! Деление на 0

> b = 10
> c = питон
> Число введено неверно

Теперь для разных типов ошибок есть свой обработчик.

Несколько типов исключений в одном блоке except

Можно также обрабатывать в одном блоке except сразу несколько исключений. Для этого они записываются в круглых скобках, через запятую сразу после ключевого слова except. Чтобы обработать сообщения «ZeroDivisionError» и «ValueError» в одном блоке записываем их следующим образом:

try:
b = float(input('b = '))
c = float(input('c = '))
a = b / c
except (ZeroDivisionError, ValueError) as er:
print(er)
else:
print('a = ', a)

При этом переменной er присваивается объект того исключения, которое было вызвано. В результате на экран выводятся сведения о конкретной ошибке.

Raise — самостоятельный вызов исключений

Исключения можно генерировать самостоятельно — для этого нужно запустить оператор raise.

min = 100
if min > 10:
raise Exception('min must be less than 10')

> Traceback (most recent call last):
> File "test.py", line 3, in <module>
> raise Exception('min value must be less than 10')
> Exception: min must be less than 10

Перехватываются такие сообщения точно так же, как и остальные:

min = 100

try:
if min > 10:
raise Exception('min must be less than 10')
except Exception:
print('Моя ошибка')

> Моя ошибка

Кроме того, ошибку можно обработать в блоке except и пробросить дальше (вверх по стеку) с помощью raise:

min = 100

try:
if min > 10:
raise Exception('min must be less than 10')
except Exception:
print('Моя ошибка')
raise

> Моя ошибка
> Traceback (most recent call last):
> File "test.py", line 5, in <module>
> raise Exception('min must be less than 10')
> Exception: min must be less than 10

Как пропустить ошибку

Иногда ошибку обрабатывать не нужно. В этом случае ее можно пропустить с помощью pass:

try:
a = 7 / 0
except ZeroDivisionError:
pass

Исключения в lambda функциях

Обрабатывать исключения внутри lambda функций нельзя (так как lambda записывается в виде одного выражения). В этом случае нужно использовать именованную функцию.

Иерархия классов для встроенных исключений в Python выглядит так:

BaseException
SystemExit
KeyboardInterrupt
GeneratorExit
Exception
ArithmeticError
AssertionError
...
...
...
ValueError
Warning

Все исключения в Python наследуются от базового BaseException:

  • SystemExit — системное исключение, вызываемое функцией sys.exit() во время выхода из приложения;
  • KeyboardInterrupt — возникает при завершении программы пользователем (чаще всего при нажатии клавиш Ctrl+C);
  • GeneratorExit — вызывается методом close объекта generator;
  • Exception — исключения, которые можно и нужно обрабатывать (предыдущие были системными и их трогать не рекомендуется).

От Exception наследуются:

1 StopIteration — вызывается функцией next в том случае если в итераторе закончились элементы;

2 ArithmeticError — ошибки, возникающие при вычислении, бывают следующие типы:

  • FloatingPointError — ошибки при выполнении вычислений с плавающей точкой (встречаются редко);
  • OverflowError — результат вычислений большой для текущего представления (не появляется при операциях с целыми числами, но может появиться в некоторых других случаях);
  • ZeroDivisionError — возникает при попытке деления на ноль.

3 AssertionError — выражение, используемое в функции assert неверно;

4 AttributeError — у объекта отсутствует нужный атрибут;

5 BufferError — операция, для выполнения которой требуется буфер, не выполнена;

6 EOFError — ошибка чтения из файла;

7 ImportError — ошибка импортирования модуля;

8 LookupError — неверный индекс, делится на два типа:

  • IndexError — индекс выходит за пределы диапазона элементов;
  • KeyError — индекс отсутствует (для словарей, множеств и подобных объектов);

9 MemoryError — память переполнена;

10 NameError — отсутствует переменная с данным именем;

11 OSError — исключения, генерируемые операционной системой:

  • ChildProcessError — ошибки, связанные с выполнением дочернего процесса;
  • ConnectionError — исключения связанные с подключениями (BrokenPipeError, ConnectionResetError, ConnectionRefusedError, ConnectionAbortedError);
  • FileExistsError — возникает при попытке создания уже существующего файла или директории;
  • FileNotFoundError — генерируется при попытке обращения к несуществующему файлу;
  • InterruptedError — возникает в том случае если системный вызов был прерван внешним сигналом;
  • IsADirectoryError — программа обращается к файлу, а это директория;
  • NotADirectoryError — приложение обращается к директории, а это файл;
  • PermissionError — прав доступа недостаточно для выполнения операции;
  • ProcessLookupError — процесс, к которому обращается приложение не запущен или отсутствует;
  • TimeoutError — время ожидания истекло;

12 ReferenceError — попытка доступа к объекту с помощью слабой ссылки, когда объект не существует;

13 RuntimeError — генерируется в случае, когда исключение не может быть классифицировано или не подпадает под любую другую категорию;

14 NotImplementedError — абстрактные методы класса нуждаются в переопределении;

15 SyntaxError — ошибка синтаксиса;

16 SystemError — сигнализирует о внутренне ошибке;

17 TypeError — операция не может быть выполнена с переменной этого типа;

18 ValueError — возникает когда в функцию передается объект правильного типа, но имеющий некорректное значение;

19 UnicodeError — исключение связанное с кодирование текста в unicode, бывает трех видов:

  • UnicodeEncodeError — ошибка кодирования;
  • UnicodeDecodeError — ошибка декодирования;
  • UnicodeTranslateError — ошибка перевода unicode.

20 Warning — предупреждение, некритическая ошибка.

💭 Посмотреть всю цепочку наследования конкретного типа исключения можно с помощью модуля inspect:

import inspect

print(inspect.getmro(TimeoutError))

> (<class 'TimeoutError'>, <class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)

📄 Подробное описание всех классов встроенных исключений в Python смотрите в официальной документации.

Как создать свой тип Exception

В Python можно создавать свои исключения. При этом есть одно обязательное условие: они должны быть потомками класса Exception:

class MyError(Exception):
def __init__(self, text):
self.txt = text

try:
raise MyError('Моя ошибка')
except MyError as er:
print(er)

> Моя ошибка


С помощью try/except контролируются и обрабатываются ошибки в приложении. Это особенно актуально для критически важных частей программы, где любые «падения» недопустимы (или могут привести к негативным последствиям). Например, если программа работает как «демон», падение приведет к полной остановке её работы. Или, например, при временном сбое соединения с базой данных, программа также прервёт своё выполнение (хотя можно было отловить ошибку и попробовать соединиться в БД заново).

Вместе с try/except можно использовать дополнительные блоки. Если использовать все блоки описанные в статье, то код будет выглядеть так:

try:
# попробуем что-то сделать
except (ZeroDivisionError, ValueError) as e:
# обрабатываем исключения типа ZeroDivisionError или ValueError
except Exception as e:
# исключение не ZeroDivisionError и не ValueError
# поэтому обрабатываем исключение общего типа (унаследованное от Exception)
# сюда не сходят исключения типа GeneratorExit, KeyboardInterrupt, SystemExit
else:
# этот блок выполняется, если нет исключений
# если в этом блоке сделать return, он не будет вызван, пока не выполнился блок finally
finally:
# этот блок выполняется всегда, даже если нет исключений else будет проигнорирован
# если в этом блоке сделать return, то return в блоке

Подробнее о работе с исключениями в Python можно ознакомиться в официальной документации.

Firstly, try / except are not functions, but statements.

To convert a string (or any other type that can be converted) to an integer in Python, simply call the int() built-in function. int() will raise a ValueError if it fails and you should catch this specifically:

In Python 2.x:

>>> for value in '12345', 67890, 3.14, 42L, 0b010101, 0xFE, 'Not convertible':
...     try:
...         print '%s as an int is %d' % (str(value), int(value))
...     except ValueError as ex:
...         print '"%s" cannot be converted to an int: %s' % (value, ex)
...
12345 as an int is 12345
67890 as an int is 67890
3.14 as an int is 3
42 as an int is 42
21 as an int is 21
254 as an int is 254
"Not convertible" cannot be converted to an int: invalid literal for int() with base 10: 'Not convertible'

In Python 3.x

the syntax has changed slightly:

>>> for value in '12345', 67890, 3.14, 42, 0b010101, 0xFE, 'Not convertible':
...     try:
...         print('%s as an int is %d' % (str(value), int(value)))
...     except ValueError as ex:
...         print('"%s" cannot be converted to an int: %s' % (value, ex))
...
12345 as an int is 12345
67890 as an int is 67890
3.14 as an int is 3
42 as an int is 42
21 as an int is 21
254 as an int is 254
"Not convertible" cannot be converted to an int: invalid literal for int() with base 10: 'Not convertible'

Ошибок не допускает только тот, кто ничего не делает и программирование не исключение. С ростом кода и объема разработки, также растет вероятность получить error в терминале. Именно по причине весовой вероятности появления ошибок исключения в python и других языках программирования — это обязательная часть.

Значения исключений и ошибок в Python

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

В Python обработка исключений имеет колоссальное значение. Неполадки возможны как элементарные, так и скрытые в особенностях языка или логике построения. Если программист считает, что пользователь никогда не сделает ошибки – он их обязательно совершит. Идеального решения в программном коде не существует и существовать не может, следовательно, добавлять исключение и уметь их обрабатывать профессиональная необходимость.

Как устроен механизм исключений

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

На курсах python https://volgograd.videoforme.ru/computer-programming-school/python-for-beginners объясняют, что обработка ошибок происходит во многом за счет пойманного exceptions. Код, который потенциально может быть проломным, оборачивается в своего рода ловушку. Если проблем нет, то все проходит стандартно, но только появляться exceptions мы выходим из потенциально проблемного участка и идем по пути исключения. По сути данный механизм можно условно сравнить if – else, когда все хорошо мы в if, когда сломалось в else (при этом в else также прилетит exceptions).

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

От ошибок в синтаксисе никто не застрахован. Конечно, значительно чаще этим грешат новички программирования. Возьмем пример:

.py

employee = [

['Иванов', 'бухгалтер'],

['Денисов', 'инженер'],

]

for employee_name, employee_post in employee:

label = 'Имя: { employee_name }. Должность: { employee_post }'.format(

employeу_name = employeу_name

employee_post = employee_post

)

print(label) # SyntaxError

Код кажется простым и понятным, но в нем скрыта едва заметная ошибка, которая не даст коду запуститься. Пример показывает, что простая запятая легко сломает программу. Естественно, в интерпретированной среде python выдает ошибку, особенно настолько элементарную. Ошибка SyntaxError иногда преследует программиста, когда меняют функции внутри библиотеки, или он просто утомился. В остальном это беда новичков, которые только знакомятся с языком и его синтаксисом.

Недостаточно памяти (OutofMemoryError)

Ошибки python вроде нехватки памяти далеко не редки, причин на то очень много. Разберём три основные:

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

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

Бесконечные циклы – когда условия выхода из цикла никогда не наступят, в какой-то момент выделяемая память просто закончиться.

Ошибка рекурсии (RecursionError)

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

Простой пример бесконечной рекурсии:

def recurs():

recurs()

recurs() # RecursionError

Ошибка отступа (IndentationError)

Виды ошибок в Питоне вроде неправильных отступов, опять же можно отнести к ошибкам новичков. В Python теле любого логического процесса обозначается четырьмя пробелами. Если есть «:», а внизу на том же уровне идет код — это явная ошибка.

Пример такой явной ошибки:

def spaceBar():

pass

spaceBar() # IndentationError

Типы исключений

Исключения позволяют застраховаться программисту от вероятных неисправностей. Более того, становиться возможным отладить и исправить программу на разных этапах разработки. Обработка исключений в Питон можно назвать фундаментальным навыком, необходимым для развития python разработчика.

Исключение берет свою основу от BaseException, базового исключения от которого наследуются все остальные, именно этот базовый класс позволяет создавать собственные исключения.

Наследуясь от базового класса, исключения делятся на:

  • SystemExit
  • KeyboardInterrupt
  • GeneratorExit
  • Exception

Exception единственное несистемное исключение, с которым работает программист. От этого класса идут следующие виды исключений.

Ошибка типа (TypeError)

Один из довольно распространённых типов ошибок проследить все цепочку наследования легко: BaseException, Exception, TypeError. Данное исключение сработает, когда указанный тип данных не существует.

Ошибка деления на ноль (ZeroDivisionError)

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

print( 0 / 0 ) # ZeroDivisionError

Встроенные исключения

Встроенные исключения – это виды ошибок в Питоне, условия исполнения которых четко прописаны в языке. Здесь можно вспомнить деление на ноль, отсутствие или лишние пробелы.

Ошибка прерывания с клавиатуры (KeyboardInterrupt)

Системное исключение KeyboardInterrupt дает прерывание программы какой-то клавишей или сочетанием клавиш, по умолчанию используется Ctrl+C. Это удобный способ прервать, к примеру, бесконечный цикл, когда явно программа работает неправильно.

Как обрабатывать исключения в Python (try except)

Стандартно в Python 3-я обработка исключений строится на try – except, эта конструкция очень часто встречающийся в разных языках программирования. Код обработки исключения выглядит так:

try: # место кода, где возможно срабатывание исключения

a= 10 / 0 # Явная арифметическая ошибка попадает в исключение ZeroDivisionError

except ZeroDivisionError: # Попадаем в исключение сработал ZeroDivisionError

a = 10 / 2 # Операция без ошибок

print( a ) # 5.0 – при делении получаем вещественное число

As — сохраняет ошибку в переменную

В Python try except текст ошибки выводится не через класс, а через экземпляр класса. Для примера попробуем узнать, какая ошибка произошла в коде:

try:

a= 10 - '10'

except Exception:

a = Exception

print( a )

В теории мы ожидаем получить текс ошибки, но результат выполнения программы будет «». Знакомый с языком программирования человек сразу поймет, что он получил не ошибку, а ссылку на класс.

Нам необходимо создать экземпляр класса. Для этого в «except» добавляется «as». Попробуем через try except python вывести ошибку правильно:

try:

a= 10 - '10'

except Exception as Ex:

a = Ex

print( a ) # unsupported operand type(s) for -: 'int' and 'str'

Теперь мы получаем текст о сработавшем исключении с пояснением ошибки.

Finally — выполняется всегда

Finally в конструкции try – except работает так же, как, например, в более знакомом программистам if – else. Попробуем разобрать на примере:

try:

a= 10 - '1' # Явная ошибка вычитания из числа строки

# a= 10 – 1 # Пример без ошибки

except Exception as Ex:

a = Ex

finally: #Все ниже сработает при любом результате

if type (a) == int: #Если все нормально сработало и мы получили число

print( f'получен результат: {a}' )

else:

print( f'произошла ошибка: {a}' )

Блок finally выполнится при любом результате работы программы, сработало или не сработало исключение.

Else — выполняется, когда исключение не было вызвано

Если except python вывод ошибки, то else это обработка, когда ошибки не произошло. Попробуем придумать пример для демонстрации:

try:

a = 10 – 1

#a = 10 - '1' # если захотим проверить пример с ошибкой

except Exception as Ex:

a = Ex

else: # код сработает только, если никаких ошибок не было

a = a * 2
finally:

print( a )

Несколько блоков except

Чем сложнее программа, тем с большим количеством ошибок приходится встречаться. Базовый try except python 3 вывести ошибку не только одним блоком. Except может быть столько, сколько возможных исключений допустимо. Попробуем реализовать в программе:

try:

a = int( input( 'Введите число : ' ))

b = 100 / a

except ZeroDivisionError:

b = 'деление на ноль'

except ValueError:

b = 'ошибка несоответствия типов'

except Exception:

b = 'что-то пошло не так'

print( f'результат работы программы : {b}' )

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

Несколько типов исключений в одном блоке except

В целом исключения определённого типа вполне возможно группировать. Здесь нет жестких ограничений. Попробуем в python try except вывести текст ошибки на примере кода:

try:

a = int(input('Введите число : '))

b = 100 / a

except (ZeroDivisionError, ValueError):

b = 'Введено недопустимое значение'

except Exception:

b = 'что-то пошло не так'

print( результат работы программы : {b}' )

В примере мы объединяем два типа ошибки, которые делают дальнейшее использование переменой недопустимым.

Raise — самостоятельный вызов исключений

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

try:

raise Exception("произошла ошибка")

except Exception as e:

print("В программе есть событие : " + str(e))

Встречаясь с raise функция или программа идет к ближайшему except Exception. Так можно не только обработать ошибку, но прописать в каком блоке кода ошибка произошла.

Как пропустить ошибку

Для программиста в python try except вывести текст ошибки важно, но не обязательно. Ошибку можно банально пропустить не пропустить без вреда для кода, рассмотрим пример:

a = 5

try:

a = a / 0

except Exception:

pass

print(a)

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

Стандартные ошибки (StandardError)

С большинством ошибок, существующих в Питоне, программист никогда не встретится, многие из них встречаются в реальных проектах слишком редко. Рассмотрим, какая в python 3 обработка ошибок часто встречается.

Арифметические ошибки (ArithmeticError)

Класс, предназначенный для обработки арифметических ошибок, от него наследуются три класса:

FloatingPointError

– неудачное выполнение операций с вещественными числами. На практике редко встречается.

OverflowErro

– результат математической операции — слишком большое число, обычно это вещественное число.

ZeroDivisionError

– операция приводит к делению на ноль.

Ошибка утверждения (AssertionError)

– класс ошибки, срабатывающий если работа функции assert возвращает ложное утверждение.

Ошибка атрибута (AttributeError)

– класс ошибок, происходящих с отсутствием атрибута функций или методов.

Ошибка импорта (ModuleNotFoundError)

– ошибка, говорящая об отсутствии установленного модуля или пакета

Ошибка поиска (LookupError)

– исключение, срабатывающее при обращении к ключу или индексу несуществующему у объекта.

Ошибка ключа

– исключение срабатывает при обращении внутри словаря к несуществующему внутри него ключу.

Ошибка индекса

– срабатывает когда указанный индекс в объекте типа словарь не существует.

Ошибка памяти (MemoryError)

– в python 3 обработка ошибок срабатывающее, когда памяти для работы программы не хватает или память переполнена.

Ошибка имени (NameError)

– связана с тем, что указываемое название переменой, класса или функции не существует.

Ошибка выполнения (Runtime Error)

– класс ошибок обозначающий, что выполнение функций невозможно или произошла ошибка при выполнении.

Ошибка типа (TypeError)

– исключение, связанное с указанием или использованием неверного типа данных.

Ошибка значения (ValueError)

– исключение чаше встречающееся во время невозможности преобразования типов данных.

Пользовательские исключения в Python

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

class MyException(Exception):

pass

try:

val = int(input("Введите число: "))

if val < 0:

raise MyException("Число меньше нуля: " + str(val))

print(val + 10)

except MyException as e:

print(e)

Недостатки обработки исключений в Python

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

Заключение

Не существует программиста, который способен писать код сразу, идеально, без малейших дефектов и уязвимостей. Python часто называют языком для новичков, но это не значит, что язык сделает все сам или додумает то, что не прописано. Исключения помогают избежать определённые ситуаций, не всех, но многих. Стоит помнить, что никакая дополнительная функция ошибок python не учит не совершать их вновь.

Обработка ошибок и исключений

Конструкция try…except…finally

Последнее обновление: 25.01.2022

При программировании на Python мы можем столкнуться с двумя типами ошибок. Первый тип представляют синтаксические ошибки (syntax error). Они появляются в результате нарушения синтаксиса
языка программирования при написании исходного кода. При наличии таких ошибок программа не может быть скомпилирована. При работе в какой-либо среде разработки, например, в
PyCharm, IDE сама может отслеживать синтаксические ошибки и каким-либо образом их выделять.

Второй тип ошибок представляют ошибки выполнения (runtime error). Они появляются в уже скомпилированной программе
в процессе ее выполнения. Подобные ошибки еще называются исключениями. Например, в прошлых темах мы рассматривали преобразование строки в число:

string = "5"
number = int(string)
print(number)

Данный скрипт успешно скомпилируется и выполнится, так как строка «5» вполне может быть конвертирована в число. Однако возьмем другой пример:

string = "hello"
number = int(string)
print(number)

При выполнении этого скрипта будет выброшено исключение ValueError, так как строку «hello» нельзя преобразовать в число:

ValueError: invalid literal for int() with base 10: 'hello'

С одной стороны, здесь очевидно,
что строка не представляет число, но мы можем иметь дело с вводом пользователя, который также может ввести не совсем то, что мы ожидаем:

string = input("Введите число: ")
number = int(string)
print(number)

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

try..except

Конструкция try..except имеет следующее формальное определение:

try:
	инструкции
except [Тип_исключения]:
	инструкции

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

После ключевого слова except опционально можно указать, какое исключение будет обрабатываться (например, ValueError или KeyError).
После слова except на следующей стоке идут инструкции блока except, выполняемые при возникновении исключения.

Рассмотрим обработку исключения на примере преобразовании строки в число:

try:
    number = int(input("Введите число: "))
    print("Введенное число:", number)
except:
    print("Преобразование прошло неудачно")
print("Завершение программы")

Вводим строку:

Введите число: hello
Преобразование прошло неудачно
Завершение программы

Как видно из консольного вывода, при вводе строки вывод числа на консоль не происходит, а выполнение программы переходит к блоку except.

Вводим правильное число:

Введите число: 22
Введенное число: 22
Завершение программы

Теперь все выполняется нормально, исключение не возникает, и соответственно блок except не выполняется.

Блок finally

При обработке исключений также можно использовать необязательный блок finally. Отличительной особенностью этого блока является то, что он выполняется
вне зависимости, было ли сгенерировано исключение:

try:
    number = int(input("Введите число: "))
    print("Введенное число:", number)
except:
    print("Преобразование прошло неудачно")
finally:
    print("Блок try завершил выполнение")
print("Завершение программы")

Как правило, блок finally применяется для освобождения используемых ресурсов, например, для закрытия файлов.

Понятие приведения типов в Python

Поскольку Python относится к языкам программирования с динамической типизацией данных, ответственность за предоставление данных нужного типа практически
полностью ложится на плечи программистов. Как следствие, им довольно часто приходится осуществлять преобразование объектов одного типа данных в другой. Например, когда пользователь вводит
с клавиатуры данные для вычислений, они поступают на обработку в строковом виде, а значит перед вычислениями возникает необходимость преобразования строкового типа данных в числовой. Если
этого не сделать, будет получена ошибка либо совсем неожиданный результат.

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

Приведением типа называется процесс преобразования значения одного типа данных в значение другого типа.

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

  • bool() – приведение к логическому типу,
  • int() – приведение к целочисленному типу,
  • float() – приведение к вещественному типу,
  • complex() – приведение к комплексному числу,
  • str() – приведение к строковому типу,
  • tuple() – приведение к кортежу,
  • list() – приведение к списку,
  • dict() – приведение к словарю,
  • set() – приведение к множеству.

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

Ниже описаны общие правила приведения типов для конструкторов без дополнительных параметров. Если вдруг возникнет необходимость в более экзотических приемах преобразования, следует обращаться
к описаниям конструкторов в справочнике встроенных функций стандартной библиотеки.

Приведение к типу bool

Во время преобразования к типу bool (логический тип данных) следующие значения рассматриваются как
False:

  • само значение False,
  • значение None,
  • нулевые числовые значения 0, 0.0 и 0+0j,
  • пустая строка «»,
  • пустые объекты: [], tuple(), {}, dict().

Все остальные значения преобразуются в значение True, включая число -1, поскольку оно представляет собой обычное
отрицательное число, отличное от нуля (см. пример №1). Тоже самое касается коллекций с одним нулевым значением, например,
[0], {0.0}, (0,), а также непустых строк, например,
‘0’ или ‘0.0’.

# False.        
print('bool(None):', bool(None))       
# False.        
print('bool(0):', bool(0))         
# False.        
print('bool(0.0):', bool(0.0))        
# False.        
print('bool(0+0j):', bool(0+0j))        
# False.        
print('bool(""):', bool(''))        
# False.        
print('bool([]):', bool([]))        
# False.        
print('bool({}):', bool({}))        
# False.        
print('bool(tuple()):', bool(tuple()))        
# False.        
print('bool(dict()):', bool(dict()))        

print()

# True.        
print('bool("0"):', bool('0'))        
# True.        
print('bool(-1):', bool(-1)) 
# True.        
print('bool([False]):', bool([False])) 
# True.        
print('bool({0,}):', bool({0,}))        
# True.        
print('bool((0,)):', bool((0,)))
bool(None): False
bool(0): False
bool(0.0): False
bool(0+0j): False
bool(""): False
bool([]): False
bool({}): False
bool(tuple()): False
bool(dict()): False

bool("0"): True
bool(-1): True
bool([False]): True
bool({0,}): True
bool((0,)): True














		
			

Пример №1. Приведение к типу bool.

Приведение к типу int

В случае приведения к типу int (целые числа):

  • Логическое значение True преобразуется в 1,
    False – в 0.
  • Вещественные числа просто усекаются до целой части. Например, в случае приведения вещественного числа -37.9
    к целочисленному типу оно будет преобразовано в число -37.
  • Если строка содержит верную запись целого числа в десятичной системе счисления, то интерпретатор в процессе приведения строки к целочисленному типу вернет это число.
  • Если строка num_str содержит верное представлением целого числа в системе счисления с указанным основанием base,
    то преобразовать ее можно в целое число при помощи конструктора типа с двумя аргументами int(num_str, base=10)
    (подробнее здесь).

Для других типов данных приведение к целочисленному типу не определено, поэтому попытка такого преобразования приведет к ошибке (см. пример №2).

# 1.        
print('int(True): ', int(True))          
# 0.        
print('int(False): ', int(False))       
# 53.        
print('int("+53"): ', int('+53'))            
# -7.        
print('int(-7.33): ', int(-7.33))        
# 0.        
print('int(.33): ', int(.33))        

# int() argument must be a ...        
# print('int(5.2+1.3j): ', int(5.2+1.3j))        
        
# int() argument must be a ...        
# print('int(None): ', int(None))         
        
# invalid literal for ...        
# print('int(""): ', int(''))        

# invalid literal for ...        
# print('int("3.7"): ', int('3.7'))         

# int() argument must be a ...        
# print('int([5]): ', int([5]))
int(True): 1
int(False): 0
int("-53"): -53
int(-7.33): -7
int(.33): 0


















		
			

Пример №2. Приведение к типу int.

Приведение к типу float

В случае приведения к типу float (вещественные числа):

  • Логическое значение True преобразуется в 1.0,
    False – в 0.0.
  • Целые числа преобразуются в вещественные простым добавлением нулевой дробной части. Например, целое отрицательное число -37
    будет преобразовано в число -37.0.
  • Если строка содержит верное представление целого числа в десятичной системе счисления, то интерпретатор в процессе приведения строки к вещественному типу вернет это число, добавив к нему
    нулевую дробную часть. При этом допускаются начальные и конечные пробельные символы, а также знаки плюса и минуса. Например, строка, содержащая запись целого отрицательного числа
    с пробелами ‘ -105 ‘ будет преобразовано в число -105.0.
  • Если строка содержит верное представление вещественного числа в десятичной системе счисления, то интерпретатор в процессе приведения строки к вещественному типу вернет это число.
    При этом допускаются начальные и конечные пробельные символы, а также знаки плюса и минуса. Например, строка, содержащая запись вещественного отрицательного числа с пробелами
    ‘ -1.5 ‘ будет преобразовано в число -1.5.
  • Также строка может представлять значения ‘NaN’, ‘Infinity’ или ‘-Infinity’.

Для других типов данных приведение к вещественному типу не определено, поэтому попытка такого преобразования приведет к ошибке (см. пример №3).

# 1.0.        
print('float(True): ', float(True))          
# 0.0.        
print('float(False): ', float(False))       
# 53.0.        
print('float(" +53"): ', float(' +53'))            
# -7.33.        
print('float("-7.33"): ', float('-7.33'))        
# 0.013.        
print('float("1.3e-2 "): ', float('1.3e-2 '))        
# nan.        
print('float("NaN"): ', float('NaN'))        
# -inf.        
print('float(" -Infinity "): ', float(' -Infinity '))        

# float() argument must be a string...        
# print('float(5.2+1.3j): ', float(5.2+1.3j))        
        
# float() argument must be a string...        
# print('float(None): ', float(None))         
        
# could not convert string to float...        
# print('float(""): ', float(''))        

# float() argument must be a string...        
# print('float([5]): ', float([5]))
float(True): 1.0
float(False): 0.0
float(" +53"): 53.0
float("-7.33"): -7.33
float("1.3e-2 "): 0.013
float("NaN"): nan
float(" -Infinity "): -inf

















		
			

Пример №3. Приведение к типу float.

Приведение к типу complex

В случае приведения к типу complex (комплексные числа):

  • Логическое значение True преобразуется в (1+0j),
    False – в 0j.
  • Целые и вещественные числа преобразуются в комплексные простым добавлением нулевой мнимой части +0j. Например, отрицательное вещественное число
    -3.7 будет преобразовано в комплексное число (-3.7+0j).
  • Если строка содержит верное представление комплексного числа, то интерпретатор в процессе приведения строки к комплексному типу вернет это число. При этом допускаются начальные и
    конечные пробельные символы, а также знаки плюса и минуса как перед действительной, так и мнимой частью. Однако пробелов между действительной и мнимой частями быть не должно! Например,
    строка, содержащая запись комплексного числа с пробелами ‘ -5.5+0.2j ‘ будет преобразовано в число (-5.5+0.2j).

Для других типов данных приведение к комплексному типу не определено, поэтому попытка такого преобразования приведет к ошибке (см. пример №4).

# (1+0j).        
print('complex(True):', complex(True))          
# 0j.        
print('complex(False):', complex(False))       
# (5.9-3.2j).        
print('complex(" +5.9-3.2j"):', complex(' +5.9-3.2j'))        
# (53+0j).        
print('complex(" 53"):', complex(' 53'))            
# (-7.33+0j).        
print('complex(" -7.33 "):', complex(' -7.33 '))        
# (0.013+0j).        
print('complex("1.3e-2 "):', complex('1.3e-2 '))        
# (nan+0j).        
print('complex("NaN"):', complex('NaN'))        
# (-inf+0j).        
print('complex(" -Infinity "):', complex(' -Infinity '))        
        
# complex() arg is a malformed string.       
# print('complex("5.2 + 1.3j"):', complex('5.2 + 1.3j'))        
        
# complex() first argument must be...        
# print('complex(None):', complex(None))         
        
# complex() arg is a malformed string.        
# print('complex(""):', complex(''))        

# complex() first argument must be...        
# print('complex([5]):', complex([5]))
complex(True): (1+0j)
complex(False): 0j
complex(" +5.9-3.2j"): (5.9-3.2j)
complex(" 53"): (53+0j)
complex(" -7.33 "): (-7.33+0j)
complex("1.3e-2 "): (0.013+0j)
complex("NaN"): (nan+0j)
complex(" -Infinity "): (-inf+0j)


















		
			

Пример №4. Приведение к типу complex.

Приведение к типу str

В случае приведения к типу str (строки) интерпретатор просто вернет строковое представление объекта, которое представлено методом приводимого объекта
object.__str__() (см. пример №5).

# True.        
print('str(True):', str(True))          
# False.        
print('str(False):', str(False))       
# (5.9-3.2j).        
print('str+5.9-3.2j:', str(+5.9-3.2j))        
# 53.        
print('str(53):', str(+53))            
# -7.33.        
print('str(-7.33):', str(-7.33))        
# 0.013.        
print('str(1.3e-2):', str(1.3e-2))        
# None.        
print('str(None):', str(None))        
# [0.5, 1,5].        
print('str([0.5, 1,5]):', str([0.5, 1,5]))                
# {'one', 'two'}.        
print("str({'one', 'two'}):", str({'one', 'two'}))                 
# (2, '3').        
print("str((2, '3')):", str((2, '3')))        
# {1: [2, True]}.        
print('str({1: [2, True]}):', str({1: [2, True]}))
str(True): True
str(False): False
str+5.9-3.2j: (5.9-3.2j)
str(53): 53
str(-7.33): -7.33
str(1.3e-2): 0.013
str(None): None
str([0.5, 1,5]): [0.5, 1, 5]
str({'one', 'two'}): {'one', 'two'}
str((2, '3')): (2, '3')
str({1: [2, True]}): {1: [2, True]}









		
			

Пример №5. Приведение к типу str.

Приведение к типу tuple

К типу tuple (кортежи) могут быть преобразованы только итерируемые объекты. При этом словари преобразуются в кортежи с ключами, теряя свои значения
(см. пример №6).

# ('a', 'b', 'c').        
print("tuple('abc'):", tuple('abc'))         
# (1, 2, 3).        
print('tuple([1, 2, 3]):', tuple([1, 2, 3]))                
# ('one', 'two').        
print("tuple({'one', 'two'}):", tuple({'one', 'two'}))                 
# (1, 2).        
print("tuple({1: 'one', 2: 'two'}):", tuple({1: 'one', 2: 'two'}))                
# ('one', 'two').        
print("tuple({'one': 1, 'two': 2}):", tuple({'one': 1, 'two': 2}))         
# (1, 2, 3).        
print("tuple(range(1, 4)):", tuple(range(1, 4)))        

# bool object is not iterable.        
# print('tuple(True): ', tuple(True))
          
# int object is not iterable.        
# print('tuple(53): ', tuple(53))
            
# NoneType object is not iterable.        
# print('tuple(None): ', tuple(None))
tuple('abc'): ('a', 'b', 'c')
tuple([1, 2, 3]): (1, 2, 3)
tuple({'one', 'two'}): ('one', 'two')
tuple({1: 'one', 2: 'two'}): (1, 2)
tuple({'one': 1, 'two': 2}): ('one', 'two')
tuple(range(1, 4)): (1, 2, 3)













		
			

Пример №6. Приведение к типу tuple.

Приведение к типу list

К типу list (списки) могут быть преобразованы только итерируемые объекты. При этом словари преобразуются в списки с ключами, теряя свои значения
(см. пример №7).

# ['a', 'b', 'c'].        
print("list('abc'):", list('abc'))         
# [1, 2, 3].        
print('list((1, 2, 3)):', list((1, 2, 3)))                
# ['one', 'two'].        
print("list({'one', 'two'}):", list({'one', 'two'}))                 
# [1, 2].        
print("list({1: 'one', 2: 'two'}):", list({1: 'one', 2: 'two'}))                
# ['one', 'two'].        
print("list({'one': 1, 'two': 2}):", list({'one': 1, 'two': 2}))         
# [1, 2, 3].        
print("list(range(1, 4)):", list(range(1, 4)))        

# bool object is not iterable.        
# print('list(True): ', list(True))          

# int object is not iterable.        
# print('list(53): ', list(53))            

# NoneType object is not iterable.        
# print('list(None): ', list(None))
list('abc'): ['a', 'b', 'c']
list((1, 2, 3)): [1, 2, 3]
list({'one', 'two'}): ['one', 'two']
list({1: 'one', 2: 'two'}): [1, 2]
list({'one': 1, 'two': 2}): ['one', 'two']
list(range(1, 4)): [1, 2, 3]













		
			

Пример №7. Приведение к типу list.

Приведение к типу set

К типу set (множества) могут быть преобразованы только итерируемые объекты. При этом словари преобразуются в множества с ключами, теряя свои значения
(см. пример №8).

# {'a', 'b', 'c'}.        
print("set('abc'):", set('abc'))         
# {1, 2, 3}.        
print('set((1, 2, 3)):', set((1, 2, 3)))                
# {1, 2}.        
print("set({1: 'one', 2: 'two'}):", set({1: 'one', 2: 'two'}))                
# {'one', 'two'}.        
print("set({'one': 1, 'two': 2}):", set({'one': 1, 'two': 2}))         
# {1, 2, 3}.        
print("set(range(1, 4)):", set(range(1, 4)))        

# bool object is not iterable.        
# print('set(True): ', set(True))          

# int object is not iterable.        
# print('set(53): ', set(53))            

# NoneType object is not iterable.        
# print('set(None): ', set(None))
set('abc'): {'b', 'a', 'c'}
set((1, 2, 3)): {1, 2, 3}
set({1: 'one', 2: 'two'}): {1, 2}
set({'one': 1, 'two': 2}): {'one', 'two'}
set(range(1, 4)): {1, 2, 3}












		
			

Пример №8. Приведение к типу set.

Приведение к типу dict

К типу dict (словари) напрямую могут быть преобразованы только итерируемые объекты, содержащие пары значений, в которых первые элементы становятся ключами
словаря, а вторые – его значениями. Например, это могут быть списки, кортежи или множества, содержащие в качестве своих элементов другие списки, кортежи или множества из двух элементов
(см. пример №9). При этом следует помнить, что только хешируемые (неизменяемые) объекты могут быть ключами словаря или элементами множества.

# {1: 'a', 2: 'b'}.        
print("dict([[1, 'a'], (2, 'b')]):", dict([[1, 'a'], (2, 'b')]))         
# {1: 'a', 2: 'b'}.        
print("dict([(1, 'a'), {2, 'b'}]):", dict([(1, 'a'), {2, 'b'}]))         

# {1: 'a', 2: 'b'}.        
print("dict(((1, 'a'), {2, 'b'})):", dict(((1, 'a'), {2, 'b'})))              
# {1: 'a', 2: 'b'}.        
print("dict(({1, 'a'}, [2, 'b'])):", dict(({1, 'a'}, [2, 'b'])))              

# {1: 'a', 2: 'b'}.        
print("dict({(1, 'a'), (2, 'b')}):", dict({(1, 'a'), (2, 'b')}))        


# unhashable type: list (списки не могут быть ключами).        
# print("dict([[[1], 'a'], (2, 'b')]):", dict([[[1], 'a'], (2, 'b')]))        

# unhashable type: list (список - недопустимый эл-т мн-ва).        
# print("dict({[1, 'a'], (2, 'b')}):", dict({[1, 'a'], (2, 'b')}))                

# dictionary update sequence element #0 has length 3; 2 is required.        
# print("dict([(1, 'a'), {2, 'b'}]):", dict([(1, 'a', 3), {2, 'b'}]))        

# bool object is not iterable.        
# print('dict(True): ', dict(True))
dict([[1, 'a'], (2, 'b')]): {1: 'a', 2: 'b'}
dict([(1, 'a'), {2, 'b'}]): {1: 'a', 2: 'b'}
dict(((1, 'a'), {2, 'b'})): {1: 'a', 2: 'b'}
dict(({1, 'a'}, [2, 'b'])): {1: 'a', 2: 'b'}
dict({(1, 'a'), (2, 'b')}): {2: 'b', 1: 'a'}


















		
			

Пример №9. Приведение к типу dict.

Краткие итоги параграфа

  • Для преобразования различных типов данных между собой в Python доступен целый ряд встроенных функций (конструкторов типов):
    bool() – приведение к логическому типу, int() – приведение к целочисленному типу,
    float() – приведение к вещественному типу, complex() – приведение к комплексному числу,
    str() – приведение к строковому типу, tuple() – приведение к кортежу,
    list() – приведение к списку, dict() – приведение к словарю,
    set() – приведение к множеству.
  • В операциях, например, с различными типами чисел или же в условных инструкциях и выражениях интерпретатор неявно (автоматически) преобразует объекты к общему типу. Однако в большинстве
    случаев это не так, поэтому следует внимательно следить за текущим типом переменной и при необходимости самостоятельно осуществлять явное приведение к нужному типу.

Помогите проекту, подпишитесь!

Подписка на учебные материалы сайта оформляется сроком на один год и стоит около 15 у.е. После
подписки вам станут доступны следующие возможности.

  • Доступ ко всем ответам на вопросы и решениям задач.
  • Возможность загрузки учебных кодов и программ на свой компьютер.
  • Доступ ко всем тренажерам и видеоурокам (когда появятся).
  • Возможность внести свой скромный вклад в развитие проекта и мира во всем мире,
    а также выразить свою благодарить автору за его труд. Нам очень нужна ваша поддержка!

Python для начинающих
На страницу подписки

Вопросы и задания для самоконтроля

1. Каким будет результат сложения двух переменных a = 5 и b = ‘7’? А если их
перемножить?

Показать решение.

Ответ. В первом случае мы получим ошибку, т.к. оператор сложения подразумевает наличие операндов одного типа, но интерпретатор в общем случае
не занимается автоматическим приведением типов, оставляя эту обязанность программистам. А вот умножение строки на число предусмотрено заранее, поэтому на выходе мы получим строку
‘77777’.

2. Приведите пример ситуации, в которой интерпретатор осуществляет неявное приведение к нужному типу.

Показать решение.

Ответ. Примерами могут служить: преобразование к вещественному типу при сложении целого и вещественного числа
(5 + 0.3) или же преобразование объектов к логическому типу в условных инструкциях и выражениях (1 if ‘ok’ else 0).

3. Какой важной особенностью должны обладать объекты, которые явно преобразуются в кортежи, списки или множества?

Показать решение.

Ответ. В кортежи, списки или множества при явном приведении типа могут быть преобразованы только итерируемые объекты. Преобразовать, например,
число в список не получится.

4. В каких случаях интерпретатор возбудит ошибки?

Показать решение.

print(bool([False]))     

print(int('7.5'))         

print(float(None))          
                       
print(float('0.55'))          
        
print(str(None))          
        
print(list(range(1, 5)))            
        
print(dict([[[5], 'пять']]))             
        
print(dict([[5, 'пять']]))

# True.        
print('bool([False]):', bool([False]))     

# invalid literal for ...        
# print('int("7.5"): ', int('7.5'))         

# float() argument must be a string...        
# print('float(None): ', float(None))          
                       
# 0.55.        
print('float("0.55"): ', float('0.55'))          
        
# None.        
print('str(None):', str(None))          
        
# [1, 2, 3, 4].        
print("list(range(1, 5)):", list(range(1, 5)))            
        
# unhashable type: list (списки не могут быть ключами).        
# print("dict([[[5], 'пять']]):", dict([[[5], 'пять']]))             
        
# {5: 'пять'}.        
print("dict([[5, 'пять']]):", dict([[5, 'пять']]))
bool([False]): True
float("0.55"):  0.55
str(None): None
list(range(1, 5)): [1, 2, 3, 4]
dict([[5, 'пять']]): {5: 'пять'}

















			

Быстрый переход к другим страницам

TraceBack: ошибки в Python

В процессе обучения, мы часто сталкиваемся с трекбеком, которым Python реагирует на возникающие ошибки. Это может быть не корректный ввод команды, неверное преобразование типов, обращение к несуществующему ключу или индексу, попытка совершить какое-то не предусмотренное действие с объектами, обратиться к несуществующей функции или методу, неправильно передать аргументы в функцию или метод… Python, встречая ошибку в синтаксисе или семантике кода, генерирует Traceback, в котором сообщает краткую информацию о том, в каком файле и в какой строке было возбуждено исключение(ошибка) и тип(название) данного исключения. Давайте посмотрим на некоторые исключения в Python:

>>> print var # Попытка вывести на экран, содержимое несуществующей переменной

Traceback (most recent call last):

  File «

«, line 1, in

NameError: name ‘var’ is not defined

>>>

Python вернул нам трекбек, с типом «NameError». Переменной с таким названием не существует. Любое обращение к несуществующей переменной, будет оканчиваться подобным исключением.

>>> a = ‘Hello’

>>> b = 2

>>> a + b

Traceback (most recent call last):

  File «

«, line 1, in

TypeError: cannot concatenate ‘str’ and ‘int’ objects

>>>

Тут мы попытались сплюсовать 2 значения — строчное и численное, на что Python выдал нам исключение «TypeError» — ошибка с типами, Не возможно совершить конгатенацию с строчным(str) и  целочисленным(int) типами данных.

>>> int(‘hello’) # Попытка приведения слова к числу

Traceback (most recent call last):

  File «

«, line 1, in

ValueError: invalid literal for int() with base 10: ‘hello’

>>>

Тут мы попытались привести к целочисленному типу строку, которая содержит слово и Python вернул нам трекбек типа «ValueError» — ошибка содержимого, ошибочный литерал строки, который не может быть приведен к int() и должен содержать в себе число в десятичной(привычной нам) системе счисления.

>>> 5/0 # Попытка деления на 0

Traceback (most recent call last):

  File «

«, line 1, in

ZeroDivisionError: integer division or modulo by zero

>>>

Классическая ошибка в математике — попытка деления на 0, которая возбуждает исключение типа «ZeroDivisionError» — Невозможность делить на 0.

>>> ‘test’.len()

Traceback (most recent call last):

  File «

«, line 1, in

AttributeError: ‘str’ object has no attribute ‘len’

>>>

Тут мы попытались вызвать несуществующий метод в объекте строки, на что Python отреагировал трекбеком типа «AttributeError» — ошибка атрибута, такого атрибута(метода) в данном объекте не предусмотрено.

Мы рассмотрели некоторые типы исключений, которые возвращает нам Python. Естественно их несколько больше, причем в процессе обучения, вы научитесь создавать свои типы исключений, которые будут носить свои названия.

Если в процессе выполнения вашего кода Python вернет трекбек, данный процесс прервется и не будет выполнен. Чтобы избежать подобной ситуации, мы можем отлавливать исключения и ориентируясь по их типу, выполнять то или иное действие, которое поможет избежать ошибки. Сама по себе ошибка будет, но вместо того, чтобы Python оборвал процесс выполнения кода, мы попросим его выполнить какие-то действия. Для этого существует конструкция try except. После оператора try, мы помещаем блок кода, в котором может возникнуть исключение и при помощи оператора except, указываем, какие действия нам необходимо выполнить, при возбуждении исключения того или иного типа.

try except

После оператора try, мы пишем блок кода, который гипотетический может вызвать ошибку, а может и не гипотетически, Т.Е. Иногда мы будем сознательно создавать и обрабатывать некоторые исключения, Т.К. Это просто будет удобно. Оператор except может отлавливать ошибки двумя способами. Если мы укажем:

try:

    блок кода, где возникнет исключение

except:

    блок кода, который будет выполняться в случае возникновения исключения

В данной структуре, оператор except, отловит любую ошибку, которая может появиться в блоке кода после try. Но ведь в одном блоке кода может возникнуть несколько ошибок. Конечно, некоторые из ошибок мы можем физически разделить на несколько блоков при условии, что эти ошибки могут возникнуть в нескольких отдельных строках, а что делать, если одна строка может возбудить несколько исключений? Это достаточно легко представить. Кпримеру в одной строке может выполняться ошибочное преобразование типов, обращение к несуществующему ключу словаря, обращение к неверному индексу списка, вызов несуществующего метода какого-то объекта… Разве этого недостаточно? Естественно стоит утверждать, что таких ошибок программист должен избежать, но иногда их избежать просто невозможно, а иногда программист сам выстраивает такую логику, чтобы воспользовавшись исключениями, построить структуру своего кода. Чтобы нам отловить какой-то конкретный трекбек, после оператора except, нужно указать тип(название) исключения, кпримеру Type Error — ошибка преобразования типов. После try, мы можем указать необходимое количество except, каждй из которых будет отлавливать свою ошибку и выполнять соответствующий для них код. Давайте посмотрим на несколько примеров:

>>> try:

…     int(‘Hello’) # Попытка преобразовать слово в число

… except:

…     print u»Ошибка преобразования типов!»

Ошибка преобразования типов!

>>>

Как видно, вместо трекбека, Python выполнил код после оператора except:

>>> d = {}

>>> d[‘one’]

Traceback (most recent call last):

  File «

«, line 1, in

KeyError: ‘one’

>>> try:

…     d[‘one’]

… except KeyError:

…     print u»Ошибка, было обращение к несуществующему ключу в словаре»

Ошибка, было обращение к несуществующему ключу в словаре

>>>

>>> a = ’10’

>>> b = ‘0’

>>> try:

…     int(a)/int(b)

… except ZeroDivisionError:

…     print u»Ошибка! Попытка деления на 0″

… except TypeError:

…     print U»Ошибка преобразования типов!»

Ошибка! Попытка деления на 0

>>>

>>> a = ‘Hello’

>>> a

‘Hello’

>>> b

‘0’

>>> try:

…     int(a)/int(b)

… except ZeroDivisionError:

…     print u»Ошибка! Попытка деления на 0″

… except ValueError:

…     print U»Ошибка преобразования типов!»

Ошибка преобразования типов!

>>>

Если помимо ошибок, которые вы можете предусмотреть, может возникнуть еще какая-то. Вконце предусмотренных except, которые будут отлавливать строго определенные исключения, можно написать except без уточнения типа исключения, который, взависимости от логики вашего кода, может обработать непредсказуемую ошибку.

else

Да-да, в конструкции try except, тоже есть необязательная часть else. Если вспомнить все, что мы знаем о операторе else в конструкциях if else, while else, for else, мы можем предположить, что необязательная часть else, будет выполнена в том случае, если в блоке кода после try, исключение так и не будет возбуждено. Т.Е. Если в блоке кода после try, все пройдет гладко и Python в течении выполнения блока кода ниразу не попытается вернуть трекбек, после выполнения блока кода заложенного после try, будет выполнен блок кода после else. Конструкция следующая:

try:

    блок кода

except:

    блок кода

else:

    блок кода

Именно в таком порядке:

>>> try:

…     10/0

… except ZeroDivisionError:

…     print u»Попытка деления на 0″

… else:

…     print u»Ошибок небыло»

Попытка деления на 0

>>> try:

…     10/2

… except ZeroDivisionError:

…     print u»Попытка деления на 0″

… else:

…     print u»Ошибок небыло»

Ошибок небыло

>>>

finally

В конструкции try except, предусмотрен еще один необязательный оператор finally, блок кода после которого будет выполнен в любом случае, Т.Е. Неважно возникнет ли исключение в блоке после try или нет, отработает ли else, если таковой будет в конструкции, блок кода после finally будет выполнен при любых обстоятельствах. Конструкция выглядит следующим образом:

try:

    блок кода

except:

    блок кода

else: (Если таковой необходим в конструкции)

    блок кода

finally:

    блок кода

Зачем нам нужен отдельный блок кода, который будет выполнен при любых условиях? Пожалуй самым ярким примером будет случай, если нам нужно будет выполнить что-то в цикле for или while, при условии, что они будут обрываться оператором continue или break, а мы помним, что при использовании этих операторов, часть кода которая находится после них, выполнена не будет. Но если break или continue будут использованы в конструкции try except, которая будет иметь часть finally, код в блоке finally будет выполнен даже при условии прерывания цикла:

>>> a = 5

>>> b = 10

>>> while True:

…     try:

…             c = b / a

…             a = a -1

…     except:

…             print u»Ошибка!»

…             break

…     finally:

…             print u»Делим на «,a,u»результат «,c

Делим на  4 результат  2

Делим на  3 результат  2

Делим на  2 результат  3

Делим на  1 результат  5

Делим на  0 результат  10

Ошибка!

Делим на  0 результат  10

>>>

Как видим, блок кода после finally сообщал нам результат все время выполнения цикла и сообщил его даже тогда, когда была произведена попытка деления на 0 и цикл был прерван оператором break.

Уведомления

  • Начало
  • » Python для новичков
  • » Помогите сделать проверку на input

#1 Янв. 16, 2020 10:02:45

Помогите сделать проверку на input

Такая проблема.

Хочу чтоб при input если тип равен int либо float выводило print ошибка

 n = input(»)
while type (n) != int:
    try:
        n = int(n)
    except ValueError:
        print(‘ошиб’)
        n = input(»)

( Т.е этот код ,когда будут вводить буквы то будет выдавать ошибку, как сделать также чтоб при вводе цифр выходила ошибка)

Отредактировано FishHook (Янв. 16, 2020 10:50:03)

Офлайн

  • Пожаловаться

#2 Янв. 16, 2020 11:47:31

Помогите сделать проверку на input

Насколько понимаю, задача исключить из ввода числовых значений?
Если да, то сделай функцию проверки, которая будет вызываться с значением из input.
Насколько знаю, input всегда возвращает только строку. При преобразовании строки во float абсолютно фиолетово: введена строка с целочисленным представлением или с “запятой”.
В функции достаточно сделать блок try для преобразования string во float. Если преобразование прошло успешно, вернуть False, если ошибка преобразования, тогда вернуть True. Далее действовать по полученному из функции результату.

Офлайн

  • Пожаловаться

#3 Янв. 16, 2020 16:48:59

Помогите сделать проверку на input

Rafik
Насколько понимаю, задача исключить из ввода числовых значений?Если да, то сделай функцию проверки, которая будет вызываться с значением из input.Насколько знаю, input всегда возвращает только строку. При преобразовании строки во float абсолютно фиолетово: введена строка с целочисленным представлением или с “запятой”.В функции достаточно сделать блок try для преобразования string во float. Если преобразование прошло успешно, вернуть False, если ошибка преобразования, тогда вернуть True. Далее действовать по полученному из функции результату.

Извини) Я не знаю функции все. Я только 4 день учу питон, поэтому) Ну мне надр показать код и объяснмть че да как

Офлайн

  • Пожаловаться

#4 Янв. 16, 2020 19:51:54

Помогите сделать проверку на input

IvanItterov
Т.е этот код ,когда будут вводить буквы то будет выдавать ошибку, как сделать также чтоб при вводе цифр выходила ошибка

а что вы хотите тогда вводить? символы ?

Офлайн

  • Пожаловаться

#5 Янв. 16, 2020 20:16:42

Помогите сделать проверку на input

я так понимаю tryexcept тут за место ifelifelse (зачем?)

 # получаем строку
n = input(»)
#проверяем тип тут if должен быть наверное
while type (n) != int:
    try:
	#если n не int делаем его им зачем
        n = int(n)
    except ValueError:
	#и если не получится это почему не получится то
        print(‘ошиб’)
        #сново ввод вы зциклить хотели наверное и где кавычки
        n = input(»)
#---------------------------------------------------------------
# я тоже из это ... новичков пэтому как новичек новичку
# бесконечный цикл с выходом по enter
while True:
	n = input("»")
	if n == "":
		break
# ну а что в строке с числами итд ... см. ниже

строка и ее методы
https://docs.python.org/3/library/string.html
или регэксп
https://docs.python.org/3/library/re.html?highlight=re#module-re

зы

IvanItterov
при вводе цифр выходила ошибка

те вам принт нужен или исключение поднять?

1. пжлст, форматируйте код, это в панели создания сообщений, выделите код и нажмите что то вроде
2. чтобы вставить изображение залейте его куда нибудь (например), нажмите и вставьте ссылку на его url

есчщо

Отредактировано AD0DE412 (Янв. 16, 2020 20:45:41)

Офлайн

  • Пожаловаться

#6 Янв. 17, 2020 06:22:54

Помогите сделать проверку на input

Примерно как-то так:

 def ne_chislo(stro):
    try:
        x = float(stro)
    except ValueError:
        return True
    return False
while True:
    n = input('>>')
    if ne_chislo(n):
        # если было введено число, то цикл вернёт пользователя на ввод значения
        # если НЕ числовое значение, прерываем цикл, т.е. идём далее
        break
    

Офлайн

  • Пожаловаться

#7 Янв. 17, 2020 10:59:18

Помогите сделать проверку на input

поправочка таки при int(str(“”)) вернет исключение

1. пжлст, форматируйте код, это в панели создания сообщений, выделите код и нажмите что то вроде
2. чтобы вставить изображение залейте его куда нибудь (например), нажмите и вставьте ссылку на его url

есчщо

Отредактировано AD0DE412 (Янв. 17, 2020 11:10:40)

Офлайн

  • Пожаловаться

#8 Март 8, 2020 11:48:13

Помогите сделать проверку на input

В функции достаточно сделать блок try для преобразования string во float. Если преобразование прошло успешно, вернуть False, если ошибка преобразования, тогда вернуть True. Далее действовать по полученному из функции результату.

Офлайн

  • Пожаловаться

  • Начало
  • » Python для новичков
  • » Помогите сделать проверку на input

Работаю с CAN адаптером напрямую через COM порт (использую CANard)

import canard, serial
from canard import can
from canard.hw import cantact

f = can.Frame(41)
f.dlc = 8
f.data = [32,23,4,5,6,7,8,9]

dev = cantact.CantactDev('COM4')
dev.set_bitrate(125000)
dev.start()
dev.send(f)
Msg = dev.recv()
dev.stop()

Передача сообщения работает корректно, но с приемом беда: ValueError: invalid literal for int() with base 16: »
Кусок кода ,на который ругается интерпретатор находится как раз в Canard’е, что странно. Вот он:

rx_str = ""
        while rx_str == "" or rx_str[-1] != 'r':
            rx_str = rx_str + self.ser.read().decode('UTF-8', 'ignore')

        # parse the id, create a frame
        frame_id = int(rx_str[1:4], 16)                       #строка с ошибкой
        frame = can.Frame(frame_id)

Буду очень благодарен, если поможете
P.S. realterm показывает пришедшее сообщение

Понравилась статья? Поделить с друзьями:
  • Python ошибка переполнения памяти
  • Python ошибка отступа неожиданный отступ
  • Python ошибка доступа
  • Python ошибка takes no arguments
  • Python ошибка random