Пробрасывание ошибок python

Мне надо сделать так, чтобы в случае возникновении любой ошибки произошли некоторые одинаковые дейтсвия и некоторые специфические для определенной ошибки. Как-то так:

try:
    doing_some_actions
except SpecialErrorOne:
    doing_special_action1
    actions_for_all_errors
except SpecialErrorTwo:
    doing_special_action2
    actions_for_all_errors
except SpecialErrorThree:
    doing_special_action3
    actions_for_all_errors

Как лучше это сделать с минимальным повторением кода ?

Если сделать так, то исключение попадает на экран, минуя SpecialError'ы:

try:
    doing_some_actions
except Exception as ex:
    actions_for_error
    raise ex
except SpecialErrorOne:
    doing_special_action1
except SpecialErrorTwo:
    doing_special_action2
except SpecialErrorThree:
    doing_special_action3

задан 19 окт 2016 в 6:47

faoxis's user avatar

faoxisfaoxis

7,60817 золотых знаков69 серебряных знаков128 бронзовых знаков

1

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

class SpecialErrorOne(Exception):
    def __init__(self):
        print('Call SpecialErrorOne')

class SpecialErrorTwo(Exception):
    def __init__(self):
        print('Call SpecialErrorTwo')

def actions_for_all_errors():
    print('Call actions_for_all_errors')

def doing_some_actions():
    raise SpecialErrorOne


if __name__ == '__main__':
    try:
        doing_some_actions()
    except Exception as ex:
        if isinstance(ex, SpecialErrorOne):
            print('doing_special_action1')
        elif isinstance(ex, SpecialErrorTwo):
            print('doing_special_action2')

        actions_for_all_errors()
        raise

ответ дан 19 окт 2016 в 8:31

vadim vaduxa's user avatar

vadim vaduxavadim vaduxa

8,89714 серебряных знаков24 бронзовых знака

0

Можно попробовать так:

try:
    doing_some_actions
    return
except SpecialErrorOne:
    doing_special_action1
except SpecialErrorTwo:
    doing_special_action2
except SpecialErrorThree:
    doing_special_action3
actions_for_all_errors

ответ дан 19 окт 2016 в 6:53

Vladimir Pavluk's user avatar

2

Я бы использовал паттерн проектирования стратегия:

  1. Класс Action, а от него уже унаследовал потомки SpecialAction1, SpecialAction2, … , SpecialActionN. Общее поведение для всех реакций на разные ошибки можно написать прямо в Action
  2. Далее блок except можно свести к одному: except (Error1, Error2, Error3) as e
  3. В типе исключения добавить код ошибки с методом error_no()
  4. Имея на руках п.3 можно порождать классы действий так: Action.make(err.error_no()).run(). Для этого нужно в базовом классе написать фабричный метод make() целью которого на основании кода ошибки создать класс реакции на ошибку

ответ дан 19 окт 2016 в 10:18

sys_dev's user avatar

sys_devsys_dev

3,9942 золотых знака18 серебряных знаков40 бронзовых знаков

3

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

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

Зачем использовать конструкции Try-Except / Try-Except-else? С помощью Try-Except и Try-Except-Else вы можете избежать многих неизвестных проблем, которые могут возникнуть из вашего кода. Например, код Python, использующий стиль LBYL (Look before you leap), может привести к race условиям. Здесь может помочь try-except. Кроме того, существуют случаи, когда ваш код критически зависит от некоторой информации, которая может устареть до момента ее получения. Например, код, вызывающий вызовы os.path.exists или Queue.full, может завершиться ошибкой, поскольку эти функции могут возвращать данные, которые устаревают к тому времени, когда вы их используете. Более разумным выбором здесь было бы придерживаться в своем коде стиля try-except-else, чтобы более надежно управлять вышеуказанными случаями.

Вызов исключений также допустимо в Python. Это означает, что вы можете бросить или вызвать исключение, когда это необходимо. Вы можете сделать это, просто вызвав в вашем коде raise Exception(‘Test error!’). Возникнувшее исключение прекратит текущее выполнение как обычно и пойдет дальше в стек вызовов, пока не будет обработано

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

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

Python: советы по использованию Try-Except, Try-Except-Else и многое другое

1. Как обращаться с произвольным исключением

Иногда вам может понадобиться способ разрешить любое произвольное исключение, а также иметь возможность отображать сообщение об ошибке или исключении.

Это легко достижимо с помощью исключений Python. Проверьте код ниже. Во время тестирования вы можете поместить код внутри блока try как в следующем примере.

try:
    #your code
except Exception as ex:
    print(ex)

2. Поймать несколько исключений в одном блоке Except

except (Exception1, Exception2) as e:
    pass

Обратите внимание, что вы можете отделить исключения от переменной запятой, которая применима в Python 2.6 / 2.7. Но вы не можете сделать это в Python 3. Поэтому вы должны использовать ключевое слово as.

3. Обработка нескольких исключений одним блоком Except

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

try:
    file = open('input-file', 'open mode')
except (IOError, EOFError) as e:
    print("Testing multiple exceptions. {}".format(e.args[-1]))

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

try:
    file = open('input-file', 'open mode')
except EOFError as ex:
    print("Caught the EOF error.")
    raise ex
except IOError as e:
    print("Caught the I/O error.")
    raise ex

Последнее, но не менее важное, это использовать исключение без упоминания какого-либо атрибута исключения.

try:
    file = open('input-file', 'open mode')
except:
    raise

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

4. Повторный проброс исключений в Python

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

Смотрите приведенный ниже пример кода.

try:
    # Преднамеренно бросить исключение.
    raise Exception('I learn Python!')
except:
    print("Entered in except.")
    # Возобновить исключение.
    raise

Вывод:

Entered in except.
Traceback (most recent call last):
  File "python", line 3, in 
Exception: I learn Python!

5. Когда использовать Else

Используйте предложение else сразу после блока try-except. Предложение else будет получено, только если не сгенерировано исключение. Оператор else всегда должен предшествовать блокам except.

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

В примере ниже, вы можете увидеть бесконечный цикл while. Код запрашивает ввод данных пользователем, а затем анализирует его, используя встроенную функцию int(). Если пользователь вводит значение ноль, тогда блоком исключений будет достигнут успех. В противном случае код будет проходить через блок else.

while True:
    x = int(input())

    try:
        result = 1 / x
    except:
        print("Error case")
        exit(0)
    else:
        print("Pass case")
        exit(1)

6. Используйте Finally

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

Ошибка поймана в блоке try. После того, как код в блоке except будет выполнен, инструкции в блоке finally будут выполнены.

Обратите внимание, что блок finally будет ВСЕГДА работать, даже если вы вернулись раньше него.

Смотрите пример ниже.

try:
    x = 1 / 0
except:
    print("Error occurred")
finally:
    print("The [finally clause] is hit")

Вывод:

Error occurred
The [finally clause] is hit

7. Используйте ключевое слово As для отлова определенных типов исключений.

С помощью <идентификатора> вы можете создать новый объект. В приведенном ниже примере мы создаем объект IOError и затем используем.

try:
    f = open("no-file")
except IOError as err:
    print("Error:", err)
    print("Code:", err.errno)

Результат:

('Error:', IOError(2, 'No such file or directory'))
('Code:', 2)

8. Лучшая практика для создания исключений

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

Плохой пример:

def bad_exception():
    try:
        raise ValueError('Intentional - do not want this to get caught')
        raise Exception('Exception to be handled')
    except Exception as error:
        print('Inside the except block: ' + repr(error))
        
bad_exception()

Результат:

Inside the except block: ValueError('Intentional - do not want this to get caught',)

Пример получше:

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

try:
    raise ValueError('Testing exceptions: The input is in incorrect order', 'one', 'two', 'four') 
except ValueError as err:
    print(err.args)

Результат:

('Testing exceptions: The input is in incorrect order', 'one', 'two', 'four')

9. Как пропустить ошибки и продолжить выполнение

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

try:
    assert False
except AssertionError:
    pass
print('Welcome to Prometheus!!!')

Результат:

Welcome to Prometheus!!!

Теперь рассмотрим некоторые из наиболее распространенных исключений Python и их примеры.

Наиболее распространенные Exception Errors:

  • IOError — происходит при ошибках файловой системы, например, если файл не открывается.
  • ImportError — Если модуль Python не может быть загружен или не найден.
  • ValueError — происходит, если функция получает аргумент правильного типа, но не подходящего значения.
  • KeyboardInterrupt — когда пользователь вводит ключ прерывания (т.е. Control-C или Del в консоли)
  • EOFError — Возникает, если входные функции (input() / raw_input()) попадают в условие конца файла (EOF), но без чтения каких-либо данных.

Примеры наиболее распространенных исключений

except IOError:
print('Error occurred while opening the file.')

except ValueError:
print('Non-numeric input detected.')

except ImportError:
print('Unable to locate the module.')

except EOFError:
print('Identified EOF error.')

except KeyboardInterrupt:
print('Wrong keyboard input.')

except:
print('An error occurred.')

Резюме — Как лучше всего использовать Try-Except в Python

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

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

Уровень сложности
Средний

Время на прочтение
8 мин

Количество просмотров 6.3K

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

  • Что такое обработка исключений?

  • Разница между оператором if и обработкой исключений.

  • Использование разделов else и finally блока try-except для организации правильного обращения с ошибками.

  • Определение пользовательских исключений.

  • Рекомендации по обработке исключений.

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

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

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

Различия между оператором if и обработкой исключений

Главные различия между оператором if и обработкой исключений в Python произрастают из их целей и сценариев использования.

Оператор if — это базовый строительный элемент структурного программирования. Этот оператор проверяет условие и выполняет различные блоки кода, основываясь на том, истинно проверяемое условие или ложно. Вот пример:

temperature = int(input("Please enter temperature in Fahrenheit: "))
if temperature > 100:
    print("Hot weather alert! Temperature exceeded 100°F.")
elif temperature >= 70:
    print("Warm day ahead, enjoy sunny skies.")
else:
    print("Bundle up for chilly temperatures.")

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

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

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

# Определение функции, которая пытается поделить число на ноль
def divide(x, y):
    result = x / y
    return result
# Вызов функции divide с передачей ей x=5 и y=0
result = divide(5, 0)
print(f"Result of dividing {x} by {y}: {result}")

Вывод:

Traceback (most recent call last):
  File "<stdin>", line 8, in <module>
ZeroDivisionError: division by zero attempted

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

Вышеописанное исключение можно обработать, обернув вызов функции divide в блок try-except:

# Определение функции, которая пытается поделить число на ноль
def divide(x, y):
    result = x / y
    return result
# Вызов функции divide с передачей ей x=5 и y=0
try:
    result = divide(5, 0)
    print(f"Result of dividing {x} by {y}: {result}")
except ZeroDivisionError:
    print("Cannot divide by zero.")

Вывод:

Cannot divide by zero.

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

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

Использование разделов else и finally блока try-except для организации правильного обращения с ошибками

При работе с исключениями в Python рекомендуется включать в состав блоков try-except и раздел else, и раздел finally. Раздел else позволяет программисту настроить действия, производимые в том случае, если при выполнении кода, который защищают от проблем, не было вызвано исключений. А раздел finally позволяет обеспечить обязательное выполнение неких заключительных операций, вроде освобождения ресурсов, независимо от факта возникновения исключений (вот и вот — полезные материалы об этом).

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

Использование разделов else и finally позволяет поступить именно так — обработать данные обычным образом в том случае, если исключений не возникло, либо обработать любые исключения, но, как бы ни развивались события, в итоге закрыть файл. Без этих разделов код страдал бы уязвимостями в виде утечки ресурсов или неполной обработки ошибок. В результате оказывается, что else и finally играют важнейшую роль в создании устойчивых к ошибкам и надёжных программ.

try:
    # Открытие файла в режиме чтения
    file = open("file.txt", "r")
    print("Successful opened the file")
except FileNotFoundError:
    # Обработка ошибки, возникающей в том случае, если файл не найден
    print("File Not Found Error: No such file or directory")
    exit()
except PermissionError:
    # Обработка ошибок, связанных с разрешением на доступ к файлу
    print("Permission Denied Error: Access is denied")
else:
    # Всё хорошо - сделать что-то с данными, прочитанными из файла
    content = file.read().decode('utf-8')
    processed_data = process_content(content)
    
# Прибираемся после себя даже в том случае, если выше возникло исключение
finally:
    file.close()

В этом примере мы сначала пытаемся открыть файл file.txt для чтения (в подобной ситуации можно использовать выражение with, которое гарантирует правильное автоматическое закрытие объекта файла после завершения работы). Если в процессе выполнения операций файлового ввода/вывода возникают ошибки FileNotFoundError или PermissionError — выполняются соответствующие разделы except. Здесь, ради простоты, мы лишь выводим на экран сообщения об ошибках и выходим из программы в том случае, если файл не найден.

В противном случае, если в блоке try исключений не возникло, мы продолжаем работу, обрабатывая содержимое файла в ветви else. И наконец — выполняется «уборка» — файл закрывается независимо от возникновения исключения. Это обеспечивает блок finally (подробности смотрите здесь).

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

Определение пользовательских исключений

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

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

Вот пример определения пользовательского исключения, названного InvalidEmailAddress:

class InvalidEmailAddress(ValueError):
    def __init__(self, message):
        super().__init__(message)
        self.msgfmt = message

Это исключение является наследником ValueError. Его конструктор принимает необязательный аргумент message (по умолчанию он устанавливается в значение invalid email address).

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

def send_email(address):
    if isinstance(address, str) == False:
        raise InvalidEmailAddress("Invalid email address")
# Отправка электронного письма

Теперь, если функции send_email() будет передана строка, содержащая неправильно оформленный адрес, то, вместо сообщения стандартной ошибки TypeError, будет выдано настроенное заранее сообщение об ошибке, которое чётко указывает на возникшую проблему. Например, это может выглядеть так:

>>> send_email(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/project/main.py", line 8, in send_email
    raise InvalidEmailAddress("Invalid email address")
InvalidEmailAddress: Invalid email address

Рекомендации по обработке исключений

Вот несколько рекомендаций, относящихся к обработке ошибок в Python:

  1. Проектируйте код в расчёте на возможное возникновение ошибок. Заранее планируйте устройство кода с учётом возможных сбоев и проектируйте программы так, чтобы они могли бы достойно обрабатывать эти сбои. Это означает — предугадывать возможные пограничные случаи и реализовывать подходящие обработчики ошибок.

  2. Используйте содержательные сообщения об ошибках. Сделайте так, чтобы программа выводила бы, на экран, или в файл журнала, подробные сообщения об ошибках, которые помогут пользователям понять — что и почему пошло не так. Старайтесь не применять обобщённые сообщения об ошибках, наподобие Error occurred или Something bad happened. Вместо этого подумайте об удобстве пользователя и покажите сообщение, в котором будет дан совет по решению проблемы или будет приведена ссылка на документацию. Постарайтесь соблюсти баланс между выводом подробных сообщений и перегрузкой пользовательского интерфейса избыточными данными.

  3. Минимизируйте побочные эффекты. Постарайтесь свести к минимуму последствия сбойных операций, изолируя проблемные разделы кода посредством конструкции try-finally или try с использованием with. Сделайте так, чтобы после выполнения кода, было ли оно удачным или нет, обязательно выполнялись бы «очистительные» операции.

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

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

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

Итоги

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

О, а приходите к нам работать? 🤗 💰

Мы в wunderfund.io занимаемся высокочастотной алготорговлей с 2014 года. Высокочастотная торговля — это непрерывное соревнование лучших программистов и математиков всего мира. Присоединившись к нам, вы станете частью этой увлекательной схватки.

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

Сейчас мы ищем плюсовиков, питонистов, дата-инженеров и мл-рисерчеров.

Присоединяйтесь к нашей команде.

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

  • Как устроен механизм исключений
  • Как обрабатывать исключения в 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 можно ознакомиться в официальной документации.

На чтение 13 мин Просмотров 4.2к. Опубликовано 12.07.2021

Содержание

  1. Введение в тему
  2. Что такое исключения
  3. Перехват исключений
  4. Несколько блоков except
  5. Вложенные блоки и else
  6. Finally
  7. Управление исключениями
  8. Пользовательские исключения
  9. Запись в лог
  10. Иерархия исключений

Введение в тему

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

Что такое исключения

Работа программиста во многом связана с возникающими в коде ошибками. Их приходится находить и исправлять. Особенно опасны так называемые гейзенбаги – ошибки, которые сложно воспроизвести. Так же существуют скрытые ошибки, их ещё можно назвать логическими. Ещё есть ошибки, которые и вовсе не зависят от программы. Представьте, у Вас есть программа-скрапер, которая автоматически скачивает картинки из соцсети. Заходит она на очередную страницу… А сервер сети поломался. Программа выдаст ошибку.

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

И так, существуют следующие виды ошибок:

  • Синтаксические – когда программист нарушает правила самого языка, к примеру, допускает опечатку в ключевом слове;
  • Логические – когда в коде используется не верная логика;
  • Ввода – когда программист предполагал от пользователя ввода одних данных, а введены другие. К примеру, создатель сайта задумывал, что число в форме будет указано с использованием точки в качестве разделителя, а пользователь ввёл «3,14». Именно этот вид ошибок – излюбленная лазейка хакеров.

Синтаксические ошибки – самые простые, поскольку интерпретатор сам сообщит Вам о них при попытке запустить скрипт.

Простой пример, напечатали команду print с большой буквы:


Print('Hello World!')
# Вывод

Traceback (most recent call last):

File "C:/Users/ivand/PycharmProjects/pythonProject/main.py", line 1, in <module>

Print('Hello World!')

NameError: name 'Print' is not defined

 

Process finished with exit code 1

Логические ошибки – самые сложные в обработке. Сложность в том, что скрипт запускается и не выдаёт никаких исключений, но результат работы отличается от ожидаемого. В чём причина и где её искать? Понятно, что использован не правильный алгоритм. В таких ситуациях можно посоветовать разбить алгоритм на части и проверять значение переменных в контрольных точках. Вот пример такой ошибки:


from random import randint

random_list = 5
sorted_list = []
for i in range(random_list):
sorted_list.append(randint(1, 99))
print(sorted_list)

for i in range(random_list - 1):
for j in range(random_list - i - 1):
if sorted_list[j] > sorted_list[j + 1]:
sorted_list[j] = sorted_list[j + 1]

print(sorted_list)
# Вывод:

 

[95, 57, 16, 29, 82]

[16, 16, 16, 29, 82]

В этом примере программист хотел сделать сортировку пузырьком, но допустил ошибку. А Вы сможете её найти?

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


x_var = input('Введите число и мы его разделим на 10 n')
print('Результат деления:', float(x_var) / 10)
# Вывод:

 

Введите число и мы его разделим на 10

3,14

Traceback (most recent call last):

File "C:/Users/ivand/PycharmProjects/pythonProject/main.py", line 2, in <module>

print('Результат деления:', float(x_var) / 10)

ValueError: could not convert string to float: '3,14'

Как вы видите, интерпретатор «выбрасывает» исключение «ValueError» — ошибка значения и останавливает выполнение кода.

Перехват исключений

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


x_var = input('Введите число и мы его разделим на 10 n')
try:
print('Результат деления:', float(x_var) / 10)
except ValueError:
print('Вы ввели число с запятой, а надо с точкой')
print('Программа завершена')
# Вывод:

Введите число и мы его разделим на 10

3,14

Вы ввели число с запятой, а надо с точкой

Программа завершена

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

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

Можно использовать несколько блоков except и обрабатывать в каждом блоке отдельный вид ошибки. Немного перепишем программу из предыдущего примера:


x_var = input('Введите число и мы разделим на него 10 n')
try:
print('Результат деления:', 10 / float(x_var))
except ValueError:
print('Вы ввели число с запятой, а надо с точкой')
except ZeroDivisionError:
print('Вы ввели ноль, но на него делить нельзя')
print('Программа завершена')
# Вывод:

Введите число и мы разделим на него 10

0

Вы ввели ноль, но на него делить нельзя

Программа завершена

Хорошей практикой является написание сперва блоков для конкретных ошибок, а затем для общих случаев, поскольку всех ситуаций не предусмотреть:


x_var = input('Введите число и мы разделим на него 10 n')
try:
Print('Результат деления:', 10 / float(x_var))
except ValueError:
print('Вы ввели число с запятой, а надо с точкой')
except ZeroDivisionError:
print('Вы ввели ноль, но на него делить нельзя')
except:
print('Не знаю что, но что-то точно пошло не так')
print('Программа завершена')
# Вывод:

Введите число и мы разделим на него 10

10

Не знаю что, но что-то точно пошло не так

Программа завершена

Вложенные блоки и else

Блоки try-except можно вкладывать друг в друга, если в этом есть необходимость.

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


x_var = input('Введите число и мы разделим на него 10 n')
try:
result = 10 / float(x_var)
try:
print('Результат деления:', result)
except:
print('Не знаю что, но что-то точно пошло не так')
else:
print('Полёт нормальный')
except ValueError:
print('Вы ввели число с запятой, а надо с точкой')
except ZeroDivisionError:
print('Вы ввели ноль, но на него делить нельзя')
else:
print('Программа выполнена без ошибок')
print('Программа завершена')
# Вывод:

Введите число и мы разделим на него 10

10

Результат деления: 1.0

Полёт нормальный

Программа выполнена без ошибок

Программа завершена

Кстати, здесь допущена логическая ошибка. Найдёте?

Finally

Встречаются ситуации, когда необходимо выполнить какую-то часть кода в независимости от того, было исключение или нет. Для этого существует блок finally:


try:
result = 10 / float(x_var)
try:
Print('Результат деления:', result)
except:
print('Не знаю что, но что-то точно пошло не так')
else:
print('Полёт нормальный')
except ValueError:
print('Вы ввели число с запятой, а надо с точкой')
except ZeroDivisionError:
print('Вы ввели ноль, но на него делить нельзя')
finally:
print('Программа завершена')
# Вывод:

Введите число и мы разделим на него 10

10

Не знаю что, но что-то точно пошло не так

Программа завершена

Управление исключениями

В Пайтоне есть возможность создавать свои виды исключений. Ниже мы рассмотрим как это делать, а ещё такую важную вещь как логгирование.

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

В Python есть ключевое слово raise. Нужно оно для того чтоб самостоятельно вызывать исключения:


raise Exception("Моя ошибка")
# Вывод:

Traceback (most recent call last):

File "C:/Users/ivand/PycharmProjects/pythonProject/main.py", line 1, in <module>

raise Exception("Моя ошибка")

Exception: Моя ошибка

Такие ошибки тоже можно ловить в try и обрабатывать в except:


x_var = float(input('Введите числоn'))
try:
if x_var > 10:
raise Exception()
except:
print('Что-то пошло не так. Возможно, число слишком большое')
# Вывод:

Введите число

11

Что-то пошло не так. Возможно, число слишком большое

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


class MyException(Exception):
def __str__(self):
return 'Число слишком большое'

x_var = float(input('Введите числоn'))
try:
if x_var > 10:
raise MyException()
except MyException:
print(MyException())
# Вывод:

Введите число

11

Число слишком большое

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


class MyException(Exception):
def __init__(self):
self.message = 'Число слишком большое'
super().__init__(self.message)

x_var = float(input('Введите числоn'))
try:
if x_var > 10:
raise MyException()
except MyException:
print(MyException())
# Вывод:

Введите число

11

Число слишком большое

Раз мы объявили метод __init__, следует сказать, что в него можно передавать аргументы:


class MyException(Exception):
def __init__(self, x):
self.x = x
self.message = 'Число {} слишком большое'.format(self.x)
super().__init__(self.message)

x_var = float(input('Введите числоn'))
if x_var > 10:
raise MyException(x_var)
# Вывод:

Введите число

11

Traceback (most recent call last):

File "C:/Users/ivand/PycharmProjects/pythonProject/main.py", line 9, in <module>

raise MyException(x_var)

__main__.MyException: Число 11.0 слишком большое

Запись в лог

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


import logging

logging.basicConfig(level=logging.DEBUG)
logging.debug(" Сообщения про отладку")
logging.info(" Информационные сообщения")
logging.warning(" Предупреждения")
logging.error(" Сообщения с ошибками")
logging.critical(" Ну очень важные сообщения")
# Вывод:

DEBUG:root: Сообщения про отладку

INFO:root: Информационные сообщения

WARNING:root: Предупреждения

ERROR:root: Сообщения с ошибками

CRITICAL:root: Ну очень важные сообщения

Параметр level= указывает, сообщения какого уровня заносить в лог. К примеру, если указать ‘level= logging.ERROR’, то логгироваться будут только сообщения уровня error и critical. Объединим логгирование и обработку исключений:


import logging

logging.basicConfig(filename="log.txt", level=logging.WARNING)
try:
print(10 / 0)
except Exception:
logging.error(str(Exception))

Содержимое файла log.txt:

ERROR:root:<class 'Exception'>

Иерархия исключений

В Python есть иерархия исключений. Это происходит из-за того, что их классы наследуются друг от друга. Вот полный список:

BaseException — базовое исключение, от которого берут начало все остальные

+SystemExit  — исключение, порождаемое функцией sys.exit при выходе из программы

+KeyboardInterrupt  — порождается при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C)

+GeneratorExit  — порождается при вызове метода close объекта generator

+Exception – исключения

++StopIteration — порождается встроенной функцией next, если в итераторе больше нет элементов

++StopAsyncIteration используется для остановки асинхронного прохода

++ArithmeticError — арифметическая ошибка

+++FloatingPointError

+++OverflowError

+++ZeroDivisionError

++AssertionError— выражение в функции assert ложно

++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

Понравилась статья? Поделить с друзьями:
  • Проверить и исправить ошибки html
  • Пробить текст на ошибки
  • Проверить железо на наличие ошибок
  • Пробел перед запятой это ошибка
  • Проверить документ на ошибки и знаки препинания