Ошибка питон интерпретатор

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

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

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

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

Table of Contents

  • Syntax Errors in Python
    • Indentation Errors
  • Exceptions, Errors, and Bugs
    • Exceptions and Errors
    • It’s Not a Feature; It’s a Bug
  • Try Block Basics: Handling Exceptions in Python
    • Handling Built-In Exceptions
    • Handling Base Class Exception Types
    • Handling Multiple Exception Types
    • Handling Base Class Exceptions: A Caveat
  • Raising Built-In and User-Defined Exceptions
  • Python Error Handling: Do’s and Don’ts

“To err is human,” and no one knows that better than software developers. In Python, as in other programming languages, learning to correctly and quickly fix the errors that we make — and to handle the errors our program can make — is an essential part of learning to program correctly. The difference between a program that handles errors well and one that does not is the difference between one that will delight your users or discourage them. For us developers, it means the difference between a system software that is easy to maintain and one that is opaque even to us.

This article will cover several aspects of successful error handling in Python, from the simple syntax errors that beginners make to discussing runtime exceptions and how to help our users be successful — whether we’re writing simple scripts for our use or serious production code for others.

The topics we’ll cover include the following:

  • Types of errors in Python
  • Python syntax errors vs. runtime exceptions
  • Handling exceptions
  • The difference between bugs, exceptions, and errors
  • Error handling mindset and best practices

Syntax Errors in Python

Syntax errors are errors that won’t even let us run our program. In other languages, these are sometimes called “compiler errors,” meaning that the parser doesn’t recognize whatever you typed as valid. Syntax errors are especially common for beginner programmers and even senior engineers who are either learning a new programming language for the first time or “context switching” between languages.

When the Python interpreter encounters a syntax error will try to point you to where the error appeared. Here’s a screenshot showing one such error:

If you’re a beginner, the critical skill to master here is to note that the error message often tells you exactly where and what you need to fix. In this case, changing the first line to "def greeting():” fixes the error, just as the error message advises.

Indentation Errors

Another error newcomers often make (especially if they switch editors a lot) is an indentation error, which is another flavor of syntax error raised when indentation is incorrect.

This error is somewhat unique to Python since Python uses indentation to identify “block structure” — lines that belong together. Other languages use keywords or curly braces to do the same thing.

Here’s an example of incorrect indentation that’s relatively easy to fix:

When correctly formatted, the lines after the if and after the else should have an additional level of indent, as shown here:

def greeting(name=None):
    if name:
        print("Hello " + name)
    else:
        print("Hello, world!")
        
greeting()

# Outputs:  Hello, world!

Indentation errors can be harder to fix when they involve mixed tabs and spaces since sometimes it won’t be immediately obvious where the problem lies. It’s best to pick an editor with good Python support, such as VSCode (with the Python extension) or PyCharm. These editors will automatically follow PEP8 guidance of four spaces per indent level. They also include tools to reformat a Python file if it’s already indented incorrectly.

Exceptions, Errors, and Bugs

Exceptions and Errors

In Java, there’s a strict distinction between the two classes, Error and Exception. An exception, also called a checked exception, must be handled in your program or it won’t compile. An error, on the other hand, does not need to be caught. The rationale behind leaving errors unchecked is the idea that your program can’t recover from them.

In Python, exceptions are always unchecked. This means that it’s up to you whether you want to handle it or not. So the line between an exception and an error is much less clear-cut. Syntax errors are always called errors, but exceptions can be named either way. For example, “OSError” is a runtime exception.

So errors and exceptions are pretty much synonyms in Python, and non-syntax errors have the following characteristics:

  • They happen while our program is running.
  • We can handle them or not. Generally, for anything going to production or another user, they should be handled and either presented as a more friendly error message or logged.

It’s Not a Feature; It’s a Bug

Let’s take the case of selecting a user by email from a database table. We can probably all agree that if that wrong table name is wrong in our code, it’s definitely a bug. It’s also a bug if the user email is not in the table and we just let the low-level exception message bubble up to the user as a nasty “500 error” (for example), instead of formatting it nicely and allowing the user to fix it.

In either case, bugs result from either code that’s so bad it doesn’t work at all or code that’s just good enough to hobble along but doesn’t provide a good user experience.

Bugs fall into many categories, so it’s impossible to cover them comprehensively, but certainly, many of them result from poor or inadequate error handling. Because this is so important, we want to discuss some best practices for handling or preventing errors.

However, before discussing best practices, we should first ensure that we have a solid grasp of the basic mechanics of exception handling in Python. This is the topic of the next section.

Try Block Basics: Handling Exceptions in Python

Handling Built-In Exceptions

Python supports many different built-in exceptions that can happen at runtime. We might try to add two types, like a string and a number, which results in a TypeError. We might open a file for reading that isn’t there and get a FileNotFoundError. We can wrap the code that might generate such an exception in a try / except block to handle such cases. Suppose we have this code:

def show_contents(filename):
    """Display the contents of a file"""
    with open(filename, "r") as f:
        contents = f.read()
        print(contents)

show_contents("here.txt")        
show_contents("not_here.txt")

Because I’m a nice person and I’m not trying to trick you with the file names, you’ve probably already guessed that “not_here.txt” will cause some difficulty. Unhandled exceptions generally look ugly, and this exception (that gets generated) is no exception (to the general rule). Here’s our output (cover your eyes for a minute):

Fixing this is straightforward. We show the code we’ve added to the show_contents function in bold below:

def show_contents(filename):
    """Display the contents of a file"""
    try:
        with open(filename, "r") as f:
            contents = f.read()
            print(contents)
    except FileNotFoundError:
        print(f"Error: file '{filename}' was not found.")

show_contents("here.txt")        
show_contents("not_here.txt")

We now display the error in a much more user-friendly way:

Reviewing the syntax for that fix, it was this:

try:
    statements that might throw an exception
    ...
except ExceptionType [as variable_name]:
    code to if exception happens

In the example above, we didn’t capture the exception. We don’t always need it, especially when we want to display a user-friendly message so the user can fix the problem.

The example below shows how to capture the exception as a variable and write it to a log.

"""Logging an exception:  logging_example.py"""

import logging

def show_contents(filename):
    """Catch an exception with variable name"""
    try:
        with open(filename, "r") as f:
            contents = f.read()
            print(contents)
    except FileNotFoundError as ex:    
        logging.exception(ex)

show_contents("not_here.txt")

Output:

ERROR:root:[Errno 2] No such file or directory: 'not_here.txt'
Traceback (most recent call last):
  File "/Users/johnlockwood/source/CodeSolid/all-private/articles/errors/logging_example.py", line 8, in show_contents
    with open(filename, "r") as f:
FileNotFoundError: [Errno 2] No such file or directory: 'not_here.txt'

The effect of this is to display it to the console by default but see the Logging Cookbook for many examples of how to configure logging in different ways.

Handling Base Class Exception Types

Some additional rules apply to Python except blocks. First, given a class hierarchy, an except block for a base class will match that type and any types derived from that base class.

Thus, for example, we could replace FileNotFoundError in the examples that we’ve shown so far with OSError (or IOError, which is an alias for it) and get the same results. For example:

# ...

try:
   # ...   
except OSError as ex:
        print(ex)

# ...

The nice thing about this change is that we will now log all the errors that derive from OSError — not just FileNotFoundError. When dealing with files, a file not being there is only one thing that can go wrong. We also have to consider that the user might not have permission to read it. Let’s say we change our test to read:

show_contents("unreadable.txt")

Before running our code, we could create a file we don’t have permission to read (at a terminal, assuming you’re on Mac or *nix or perhaps WSL in Windows):

# Create a file:
touch unreadable.txt

# Make it write-only
chmod 200 unreadable.txt

Now when we run our code, it displays the following error message:

[Errno 13] Permission denied: 'unreadable.txt'

Handling Multiple Exception Types

For each try block, we can add multiple except blocks, for example:

try:
    # Open a file, etc.
except FileNotFoundError as ex:            
    print(f"File {filename} doesn't exist")
except OSError as ex:
    logging.exception(ex)

In this example, we print a user-friendly message if the file is not found, but if anything else happens, we log the error.

Note that FileNotFoundError is derived from OSError, so it must come before OSError to make this work. This makes sense because of the point we made earlier — that a base class except block will catch any exceptions of a derived class. Because of this, the base class must come last because it is a “catch-all”.

Handling different related exceptions differently can be helpful for the following cases:

  • You need highly customized error messages for the end user rather than a reasonable default.
  • Depending on the exception, a different team may need to look at it. There may be some Exceptions that are user errors, for example, but others that a developer on the team needs to investigate.

For other cases, we can weigh the improved granularity of specific exceptions with the increased code complexity. More isn’t always better.

Handling Base Class Exceptions: A Caveat

If you’re trying to handle any possible exception your program can raise, you need to be aware of two things. First, if you’re using PyCharm, it will warn you that your exceptions should be more granular. I don’t always follow this advice, but one thing you definitely shouldn’t do is this:

# DON'T DO THIS!!!

# ...
except BaseException:
    # ...

The reason is that BaseException is the parent of all exceptions in Python. This includes exceptions you should catch as well as many exceptions that you shouldn’t. Some examples of exceptions you shouldn’t catch include the user hitting the interrupt key (typically CTRL-C) to quit the program or the exception that’s raised when a generator or coroutine is closed.

Generally speaking, when catching a category of exceptions, you should only go as high up as you need to go. However, if you really need to ignore PyCharm’s warning and catch everything, then “except Exception” is your friend.

The Exception class in Python is the root of many exception classes defined in Python, and it’s also meant to be the root of any user-defined exceptions you might create.

Raising Built-In and User-Defined Exceptions

In addition to handling exceptions, you can also raise them, using the raise keyword and an instance of an exception class. Here’s a contrived example:

def order_widget(widget):

    # Gadgets are dangerous
    if widget == "gadget":
        raise Exception("Gadgets make our warehouse catch fire. Sorry.")

    print(f"Placing an order for {widget}.  Thanks!")

If an order is placed for a gadget, the line ordering the widget will never be reached, because an exception will be thrown.

There are a couple of things to point out about this code. First, if you raise an exception in your application code like this, it needs to be in the context of an “outer” exception handler in the same function, or a function calling you, etc.

Secondly, for a case like this where we’re doing input validation, we can sometimes simplify it by using Python’s assert keyword instead of raise. If we know our user interface code doesn’t allow gadgets to be entered in our present code, we might still add a defensive assert in case that changes:

def order_widget(widget):
    # Don't send widgets.  Remember what happened to Crispy Bob
    assert widget != "gadget"
    
    print(f"Placing an order for {widget}.  Thanks!")

I’m going to miss Crispy Bob.

In application code, we often need to handle exceptions rather than raise new ones. Raising exceptions does incur some overhead. Also, the application may be able to handle the condition in another way, like wrapping the gadget in a fireproof gadget purse.

However, it’s often the case when developing a module or library that we’ll need to create user-defined exceptions and raise them when something goes wrong. If this is something you need to do or are considering doing, we have a separate article that discusses how to design and write Python custom exceptions.

Python Error Handling: Do’s and Don’ts

Now that we’ve covered the syntax and examples of handling Python errors, it’s time to take a step back and discuss some general strategies for dealing with program errors. Some of this will recap what we’ve discussed along the way, but some of it will be new.

  • DO: Use Python’s help function to understand what exceptions a function will raise. For example, the beginning of text returned by help(open) tells us that this function will “Raise OSError upon failure.”
  • To support this for other developers who use code you write, you should provide a docstring comment for every function that tells the user what exceptions might occur. This is especially important for library developers, but it’s a best practice in application development as well.
  • DO: Avoid long chains of complex “except” clauses unless you have a good reason for them. Catching a well-chosen base class that’s common to every class of error that might be thrown might simplify your code. But see the next point as well.
  • When handling a base class exception, only cover the necessary cases. You should never write “except BaseException” and use “except Exception” sparingly as well.
  • DO consider using assert for input validation for “backend” (non-user-facing) code. Don’t use it if you need to display a friendly user message.
  • DON’T rely on exceptions for simple flow control, and try to write code that makes exceptions rare. For example, if you’re creating a function that returns a list, don’t return None if there are no elements — return an empty list. Checking the length or using a loop in the caller will work as expected, not raise an exception.
  • Exceptions should really be exceptional — things that shouldn’t happen often if at all. Consider using error codes and error messages for functions that can have more than one expected error condition.
  • DO know what error codes are expected for the domain you’re programming. For example, web APIs should return well-known HTTP error codes. (See the class http.HTTPStatus in the Python runtime library, for example).
  • DO add logging to any kind of server or backend code with no direct user interface. This includes model and controller code in Flask, Django, etc., as well as AWS Lambda functions and other service code.
  • Unless doing so would expose Personal Identifiable Information (PII), which should not be included in the logs, logging should include call stack information to simplify troubleshooting. As we’ve seen, logging.exception can be used to do this.
  • Use a function in the logging module appropriate to the information you’re providing. If it’s not an error, use debug or info.
  • Server output should be sparse (not displaying debug or info level detail) by default, but to do that effectively, you should have a way to change the logging level of the server dynamically without re-releasing the software.
  • DO spend enough time getting logging right. Remember, it’s not a question of whether something will happen in production. Something will happen in production, so the choice is to add logging during the day when you’re fresh or do it under pressure at night while listening to big shots complain on an all-hands call. Make it easy on yourself and do it during the day.
  • DO make sure your test cases cover exception cases in addition to the “happy path.”
  • DO keep logging and error handling simple. Sometimes software developers can get carried away writing sophisticated frameworks for things. In general, however, Python has all the tools you need for logging and error handling as part of the runtime library.

OK, that’s a long list, but an important one. There have been many software magic bullets over the years that were going to help us create better software, but effective error handling is one that has withstood the test of time. Using Python’s error-handling tools is hardly glamorous work, but the result is professional-quality software.

Понятие исключений и ошибок

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

# Синтаксические ошибки обнаружить легко.

# Имя переменной начали с цифры.
# SyntaxError: invalid decimal literal
# 35_days = 35

# Строка должна содержать запись целого числа.
# ValueError: invalid literal for int() with base 10: 'три'
# num = int('три')    

# Числа и строки складывать нельзя.
# TypeError: unsupported operand type(s) for +: 'int' and 'str'
# res = 5 + 'один'     

# Логические ошибки всплывут потом.    

# На первый взгляд все верно, и программа даже будет  
# работать, но только до тех пор, пока пользователь 
# не введет ноль или неприводимое к числу значение.
a = int(input('Введите число: '))
print(10/a)
Введите число: 0
ZeroDivisionError: division by zero

















		
			

Пример №1. Синтаксические и логические ошибки в Python.

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

Инструкция try/except/else/finally

Пожалуй, основной «рабочей лошадкой» по обработке исключений в Python является составная инструкция
try/except/else/finally, которая имеет следующий общий формат:

# Сначала выполняется основной блок инструкций.
try:
    <Основные инструкции>     
# Запускается, если в блоке try возникло исключение Exception_1.
except Exception_1:
    <Инструкции обработки исключения>     
# Запускается, если возникло любое из перечисленных исключений.
except (Exception_2, Exception_3):
    <Инструкции обработки исключений>     
# Работаем с экземпляром Exception_4, как с err.
except Exception_4 as err:
    <Инструкции обработки исключения>     
# Запускается для всех видов исключений.                    
except:
    <Инструкции обработки исключений>     
# Запускается, если в блоке try не возникло исключений.
else:
    <Дополнительные инструкции>
# Запускается в любом случае.
finally:
    <Финальные инструкции>

Первыми выполняются инструкции основного блока try. При обнаружении в нем ошибок, интерпретатор пытается найти соответствующий
возникшему исключению блок except и, в случае наличия такового, выполняет его инструкции. После того как исключение будет
обработано, оно уничтожается, а программа пытается продолжить работу в штатном режиме. Если же среди имеющихся блоков except
соот­ветствия найдено не будет, исключение переадресуется инструкции try, стоящей
выше в программе, или на верхний уровень процесса, что скорее всего вынудит интерпретатор аварийно завершить работу программы и вывести сообщение об ошибке по
умолчанию. В случае отсутствия ошибок в блоке try интерпретатор пропускает все блоки except и
начинает выполнять инструкции необязательного блока else, который разрешается использовать только при наличии хотя бы одного блока
except. При этом стоит помнить, что при наличии ошибок в блоке try инструкции данного блока
выполняться не будут. Что касается необязательного блока finally, то он используется для каких-либо завершающих операций, например,
закрытия файлов или открытых соединений с сервером. Его инструкции выполняются всегда, вне зависимости от того, возникли исключения в каком-либо блоке, включая блок
else, или нет (см. пример №2).

try:
    # Здесь исключения могут возбудиться из-за 
    # ввода нечислового значения или нуля.
    a = int(input('Введите число: '))
    print('10/{} = {}'.format(a, 10/a))    
# Если введено не целое число.
except ValueError:
    print('Введите целое число!')
# Если введен ноль.
except ZeroDivisionError:
    print('На ноль делить нельзя!')
# Выполнится только при отсутствии ошибок.	
else:
    print('Операция прошла успешно!')
# Выполняется в любом случае.
finally:
    print('Для завершения нажмите «Enter»!')    
    # Чтобы окно консоли не закрылось. 
    input()
Введите число: 0
На ноль делить нельзя!
Для завершения нажмите «Enter»!

-------------------------------

Введите число: один
Введите целое число!
Для завершения нажмите «Enter»!

-------------------------------

Введите число: 20
10/20 = 0.5
Операция прошла успешно!
Для завершения нажмите «Enter»!


			

Пример №2. Инструкция try/except/else/finally в Python (часть 1).

Стоит заметить, что в отличие от блоков except блок finally не останавливает распространение
исключений до вышестоящей инструкции try или до обработчика исключений по умолчанию, т.е. в случае возникновения ошибок
инструкции, следующие за блоком finally в программе, выполняться не будут (см. пример №3).

# Внешняя инструкция try.
try:
    # Внутреняя инструкция try.
    try:
        # Здесь исключения могут появиться из-за 
        # ввода нечислового значения или нуля.
        a = int(input('Введите число: '))
        print('10/{} = {}'.format(a, 10/a))    
    # Выполняется в любом случае.
    finally:
        print('Внутренний блок finally.')    
    
    # Выполняется при отсутствии ошибок
    # во внутреннем блоке try.
    print('Все ОК! Ошибок нет!')
    
# Если введено не целое число или ноль.
except (ValueError, ZeroDivisionError):
    print('Неверный ввод!')
# Выполнится только при отсутствии ошибок.	
else:
    print('Операция прошла успешно!') 
# Выполняется в любом случае.
finally:
    print('Внешний блок finally.')
    # Чтобы окно консоли не закрылось. 
    input() 
Введите число: 7
10/7 = 1.4285714285714286
Внутренний блок finally.
Все ОК! Ошибок нет!
Операция прошла успешно!
Внешний блок finally.

------------------------

Введите число: 0
Внутренний блок finally.
Неверный ввод!
Внешний блок finally.












		
			

Пример №3. Инструкция try/except/else/finally в Python (часть 2).

Если необходимо перехватывать сразу все возможные исключения, разрешается использовать инструкцию except без указания классов исключений.
Эта особенность может быть весьма удобна при разработке своих собственных обработчиков ошибок. Однако при использовании такого варианта могут перехватываться нежелательные
системные исключения, не связанные с работой создаваемого программного кода, а также случайно может прерываться распространение исключений, предназначенных для других
обработчиков. Данная проблема была частично решена в Python 3.0 за счет введения альтернативы в виде суперкласса
Exception, представляющего все прикладные исключения, но игнорирующего исключения, связанные с завершением программы (см. пример
№4).

# Основной блок try.
try:
    # Здесь исключения могут возбудиться из-за 
    # ввода нечислового значения или нуля.
    a = int(input('Введите число: '))
    print('10/{} = {}'.format(a, 10/a))    
     
# Выводим строковое представление исключения.
except Exception as err:
    print(err)
# Выполнится только при отсутствии ошибок.	
else:
    print('Операция прошла успешно!') 
# Выполняется в любом случае.
finally:
    # Чтобы окно консоли не закрылось. 
    input() 
Введите число: one
invalid literal for int() with base 10: 'one'

------------------------

Введите число: 0
division by zero

------------------------

Введите число: 10
10/10 = 1.0
Операция прошла успешно!


		
			

Пример №4. Инструкция try/except/else/finally в Python (часть 3).

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

Инструкция raise

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

try:
    # Возбудим исключение IndexError принудительно.
    # Экземпляр исключения создается автоматически.
    raise IndexError    
# Обработаем его.
except IndexError:
    print('Перехватили IndexError!')

try:
    # Все тоже самое, но здесь создаем экземпляр сами.
    raise IndexError()   
# Обработаем его.
except IndexError:
    print('Перехватили IndexError!')  
    # Вложенная инструкция try.
    try:
        # Возбудили последнее исключение еще раз.
        raise   
    # Обработаем его.
    except IndexError:
        print('Перехватили IndexError!')
Перехватили IndexError!
Перехватили IndexError!
Перехватили IndexError!
















		
			

Пример №5. Инструкция raise в Python (часть 1).

Инструкция raise может использоваться для явного возбуждения не только встроенных исключений, но и созданных пользователем.
Пользовательские исключения представляют собой самые обычные классы, наследуемые от классов встроенных исключений, чаще всего от класса
Exception (см. пример №6).

# Создаем свой класс исключений, который 
# наследуется от встроенного Exception.
class OnlyAlpha(Exception): 
    # Переопределим строковое представление.
    def __str__(self): 
        return 'Разрешены только буквы!'

# Определим функцию проверки строки на
# наличие сторонних небуквенных символов.
def check_for_alpha(s):
    # Если присутствуют не только буквы.  
    if not s.isalpha():
        # Возбуждаем экземпляр своего исключения.
        raise OnlyAlpha()       

# Проверим, как все работает.
try:
    # Просим ввести строку.
    s = input('Введите имя: ')
    # Проверяем ввод.    
    check_for_alpha(s)
# Обрабатываем польз. исключение.
except OnlyAlpha as err:
    # Строковое представление экз.
    print(err)
    print('Попробуйте еще раз!')    
# Если все прошло гладко.
else:
    # Выводим введенное имя.
    print('Привет, {}!'.format(s))
# В любом случае дополняем сообщением.
finally:       
    print('Имя – это ваш ник и логин!')
Введите имя: okpython
Привет, okpython!
Имя – это ваш ник и логин!

--------------------------

Введите имя: okpython.net
Разрешены только буквы!
Попробуйте еще раз!
Имя – это ваш ник и логин!





















		
			

Пример №6. Инструкция raise в Python (часть 2).

Стоит добавить, что инструкция raise может использоваться и в формате raise/from, который используется
значительно реже, поэтому здесь мы его рассматривать не будем. Однако не поленитесь и самостоятельно посетите подраздел
«The raise statement» раздела «Simple statements» официального
справочника языка, где хотя бы бегло ознакомьтесь и с этим вариантом инструкции.

Инструкция assert

Инструкция assert представляет собой компактный условный вариант инструкции raise,
предназначенный в основном для возбуждения исключений на этапе отладки программы. В общем виде ее можно представить в формате
assert condition[, message], где condition – это условие, при невыполнении которого
(возвращается False) будет возбуждено встроенное исключение AssertionError, а также при необходимости
выведено необязательное сообщение message (см. пример №7).

# Допустим мы пишем функцию для расчета среднего
# значения чисел переданного ей списка.
def avg(li):
    len_li = len(li)
    # Список не должен быть пустым.
    assert len_li != 0, 'Список пуст!'    
    # Возвращаем среднее значение.
    return round(sum(li)/len_li, 3)

try:
   # Запускаем функцию.  
   res = avg([]) 
# Отлавливаем исключение для обработки.
except AssertionError as my_err:
    print(my_err)
# Результат выводим, если все в порядке.
else:
    print('Среднее значение: {}'.format(res)) 
Список пуст!















		
			

Пример №7. Инструкция assert в Python.

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

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

  • Основной инструкцией для обработки исключений в Python является составная инструкция try/except/else/finally.
    Если в инструкциях обязательного блока try возникают ошибки, интерпретатор пытается перехватить и обработать их с помощью блоков
    except. В случае отсутствия соответствий исключение передается инструкции try, стоящей выше в программе,
    или на верхний уровень процесса. Необязательный блок else выполняется только при отсутствии ошибок, а необязательный блок
    finally выполняется всегда. При этом в отличие от блоков except блок
    finally не останавливает распространение исключений до вышестоящей инструкции try или до обработчика
    исключений по умолчанию, поэтому в случае возникновения ошибок инструкции, следующие за блоком finally в программе, выполняться не будут.
  • В стандартной библиотеке Python присутствует внушительный набор готовых классов, представляющих различные виды исключений и синтаксических
    ошибок. Все они перечислены в разделе Built-in exceptions, где также представлена и подробная
    иерархия имеющихся классов исключений.
  • Важно помнить, что при использовании блока except без указания класса перехватываемого исключения интерпретатор будет пытаться перехватить
    все имеющиеся виды встроенных исключений. Однако нужно быть осторожным при использовании такого варианта инструкции воизбежание перехвата нежелательных системных исключений,
    не связанных с работой создаваемого программного кода.
  • Для явного возбуждения исключений в Python предназначена инструкция raise, которой необходимо через
    пробел передавать имя класса или экземпляра возбуждаемого исключения. Данная инструкция может использоваться для явного возбуждения не только встроенных исключений, но
    и созданных пользователем. Пользовательские исключения представляют собой самые обычные классы, наследуемые от классов встроенных исключений, чаще всего от класса
    Exception.
  • Для возбуждения исключений на этапе отладки программы предназначена инструкция assert condition[, message], где
    condition – это условие, при невыполнении которого (возвращается False) будет возбуждено
    встроенное исключение AssertionError, а также при необходимости выведено необязательное сообщение message.
    Использовать инструкцию следует главным образом для проверки соблюдения ограничений, накладываемых самим программистом, а не для перехвата настоящих ошибок, которые могут
    быть спокойно перехвачены интерпретатором Python.

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

1. В каком случае выполняется код блока else составной инструкции
try/except/else/finally?

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

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

2. Что произойдет с программой в случае возбуждения исключения, если в ней не предусмотреть его обработку?

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

Ответ. В таком случае исключение будет передано обработчику предоставляемому интерпретатором по умолчанию.
Этот обработчик выведет сообщение об ошибке и завершит программу.

3. Перечислите верные форматы использования инструкции try:
try/except/else, try/else, try/finally,
try/except/finally, try/else/finally.

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

Ответ. Блок else может использоваться только при наличии хотя бы одного блока
except, следовательно варианты try/else и try/else/finally
недопустимы.

4. В каком случае выполняется код блока finally?

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

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

5. Присутствуют ли в коде условия ошибки? Проверьте свой ответ, запустив код на исполнение.
Показать решение.

try:
    a = 5; b = 0
    n = a/b   
exept Exeption as err:
    print('Ошибка: «{}».'.format(err))
else:
    print('a/b = {}'.format(n)) 
finally: 
    print('Обработка завершена!')

try:
    a = 5; b = 0
    n = a/b   
# Правильно писать except и Exception.
except Exception as err:
    print('Ошибка: «{}».'.format(err))
else:
    print('a/b = {}'.format(n)) 
finally: 
    print('Обработка завершена!')
Ошибка: «division by zero».
Обработка завершена!







			

6. Имеется ли в Python возможность создавать и возбуждать исключения вручную?

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

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

7. Для чего служит инструкция assert?

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

Ответ. Для возбуждения исключений на этапе отладки программы предназначена инструкция
assert condition[, message], где condition – это условие, при невыполнении
которого (возвращается False) будет возбуждено встроенное исключение AssertionError,
а также при необходимости выведено необязательное сообщение message. Использовать инструкцию следует главным образом
для проверки соблюдения ограничений, накладываемых самим программистом, а не для перехвата настоящих ошибок, которые могут быть спокойно перехвачены
интерпретатором Python.

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

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

The most common reason of an error in a Python program is when a certain statement is not in accordance with the prescribed usage.
Such an error is called a syntax error. The Python interpreter immediately reports it, usually along with the reason.

>>> print "hello"
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("hello")?

In Python 3.x, print is a built-in function and requires parentheses. The statement above violates this usage and hence syntax error is displayed.

Many times though, a program results in an error after it is run even if it doesn’t have any syntax error. Such an error is a runtime error, called an exception.
A number of built-in exceptions are defined in the Python library.
Let’s see some common error types.

The following table lists important built-in exceptions in Python.

Exception Description
AssertionError Raised when the assert statement fails.
AttributeError Raised on the attribute assignment or reference fails.
EOFError Raised when the input() function hits the end-of-file condition.
FloatingPointError Raised when a floating point operation fails.
GeneratorExit Raised when a generator’s close() method is called.
ImportError Raised when the imported module is not found.
IndexError Raised when the index of a sequence is out of range.
KeyError Raised when a key is not found in a dictionary.
KeyboardInterrupt Raised when the user hits the interrupt key (Ctrl+c or delete).
MemoryError Raised when an operation runs out of memory.
NameError Raised when a variable is not found in the local or global scope.
NotImplementedError Raised by abstract methods.
OSError Raised when a system operation causes a system-related error.
OverflowError Raised when the result of an arithmetic operation is too large to be represented.
ReferenceError Raised when a weak reference proxy is used to access a garbage collected referent.
RuntimeError Raised when an error does not fall under any other category.
StopIteration Raised by the next() function to indicate that there is no further item to be returned by the iterator.
SyntaxError Raised by the parser when a syntax error is encountered.
IndentationError Raised when there is an incorrect indentation.
TabError Raised when the indentation consists of inconsistent tabs and spaces.
SystemError Raised when the interpreter detects internal error.
SystemExit Raised by the sys.exit() function.
TypeError Raised when a function or operation is applied to an object of an incorrect type.
UnboundLocalError Raised when a reference is made to a local variable in a function or method, but no value has been bound to that variable.
UnicodeError Raised when a Unicode-related encoding or decoding error occurs.
UnicodeEncodeError Raised when a Unicode-related error occurs during encoding.
UnicodeDecodeError Raised when a Unicode-related error occurs during decoding.
UnicodeTranslateError Raised when a Unicode-related error occurs during translation.
ValueError Raised when a function gets an argument of correct type but improper value.
ZeroDivisionError Raised when the second operand of a division or module operation is zero.

IndexError

The IndexError is thrown when trying to access an item at an invalid index.

>>> L1=[1,2,3]
>>> L1[3]
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
            
L1[3]
IndexError: list index out of range

ModuleNotFoundError

The ModuleNotFoundError is thrown when a module could not be found.

>>> import notamodule
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
            
import notamodule
ModuleNotFoundError: No module named 'notamodule'

KeyError

The KeyError is thrown when a key is not found.

>>> D1={'1':"aa", '2':"bb", '3':"cc"}
>>> D1['4']
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>

            
D1['4']
KeyError: '4'

ImportError

The ImportError is thrown when a specified function can not be found.

>>> from math import cube
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
            
from math import cube
ImportError: cannot import name 'cube'

StopIteration

The StopIteration is thrown when the next() function goes beyond the iterator items.

>>> it=iter([1,2,3])
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
            
next(it)
StopIteration

TypeError

The TypeError is thrown when an operation or function is applied to an object of an inappropriate type.

>>> '2'+2
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
            
'2'+2
TypeError: must be str, not int

ValueError

The ValueError is thrown when a function’s argument is of an inappropriate type.

>>> int('xyz')
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
            
int('xyz')
ValueError: invalid literal for int() with base 10: 'xyz'

NameError

The NameError is thrown when an object could not be found.

>>> age
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
            
age
NameError: name 'age' is not defined

ZeroDivisionError

The ZeroDivisionError is thrown when the second operator in the division is zero.

>>> x=100/0
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
            
x=100/0
ZeroDivisionError: division by zero

KeyboardInterrupt

The KeyboardInterrupt is thrown when the user hits the interrupt key (normally Control-C) during the execution of the program.

>>> name=input('enter your name')
enter your name^c
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
            
name=input('enter your name')
KeyboardInterrupt

Learn how to handle exceptions in Python in the next chapter.

A runtime error is a type of error that occurs during program execution. The Python interpreter executes a script if it is syntactically correct. However, if it encounters an issue at runtime, which is not detected when the script is parsed, script execution may halt unexpectedly.

What Causes Runtime Errors

Some of the most common examples of runtime errors in Python are:

  • Division by zero.
  • Using an undefined variable or function name.
  • Performing an operation on incompatible types.
  • Accessing a list element, dictionary key or object attribute that does not exist.
  • Accessing a file that does not exist.

Python Runtime Error Examples

Here’s a few examples of runtime errors in Python:

Division by zero

If a number is divided by zero in Python, a runtime error is raised:

print(100/0)

In the above example, a number is attempted to be divided by zero. Running the above code raises a ZeroDivisionError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    print(100/0)
ZeroDivisionError: division by zero

Using an undefined variable or function name

A runtime error is raised if an attempt is made to access an identifier, such as a variable or function name, that is not declared previously:

print(myString)

In the above example, an undefined identifier myString is attempted to be accessed. Running the above code raises a NameError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    print(myString)
NameError: name 'myString' is not defined

Performing an operation on incompatible types

If an operation, such as addition, multiplication etc., is performed between incompatible data types, a runtime error is raised:

myString = "Hello World"
myNumber = 100
print(myString + myNumber)

In the above example, a string is attempted to be concatenated with a number. Since these types are incompatible, a TypeError is raised when the above code is executed:

File "main.py", line 3, in <module>
    print(myString + myNumber)
TypeError: can only concatenate str (not "int") to str

Accessing a non-existent list element, dictionary key or object attribute

If an attempt is made to access a non-existent index or element in a list, dictionary or   object, a runtime error is raised.

numbers = [1, 2, 3]
print(numbers[3])

In the above example, an attempt is made to access an item in a list using an out-of-range index, which raises an IndexError:

Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(numbers[3])
IndexError: list index out of range.

Accessing a file that does not exist

If a file that does not exist is attempted to be accessed, a runtime error is raised:

open("myFile.txt", "r")

In the above example, a non-existent file myFile.txt is attempted to be opened in read-only mode, which raises a FileNotFoundError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    open("myFile.txt", "r")
FileNotFoundError: [Errno 2] No such file or directory: 'myFile.txt'

How to Fix Runtime Errors in Python

To fix runtime errors in Python, the following steps can be taken:

  1. Identify the error message and note the specific problem being reported.
  2. Check the code for logical, mathematical or typographical errors.
  3. Ensure all identifiers are defined properly before being used.
  4. Make sure the correct data types are being used and are being used correctly.
  5. Verify that list items, dictionary keys, and other objects are being accessed using valid indices or keys.
  6. If necessary, consult the documentation for the relevant library or module.

Track, Analyze and Manage Errors With Rollbar

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Python errors easier than ever. Try it today!

Понравилась статья? Поделить с друзьями:

Не пропустите эти материалы по теме:

  • Яндекс еда ошибка привязки карты
  • Ошибка плагина честный знак
  • Ошибка питон indentationerror unexpected indent
  • Ошибка плагина рутокен
  • Ошибка питания ядра при игре

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии