Мир Python: исключения | Python для продвинутых
Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером
Введение
В этом уроке вы узнаете о важном средстве языка, без которого крупная программа не может обойтись. Речь пойдет об исключениях. Что это такое, как ими пользоваться и как создавать собственные?
Исключительные ситуации или исключения (exceptions) – это ошибки, обнаруженные при исполнении. Например, к чему приведет попытка чтения несуществующего файла? Или если файл был случайно удален пока программа работала? Такие ситуации обрабатываются при помощи исключений.
Если же Python не может понять, как обойти сложившуюся ситуацию, то ему не остается ничего кроме как поднять руки и сообщить, что обнаружил ошибку. В общем, исключения необходимы, чтобы сообщать программисту об ошибках.
Простейший пример исключения — деление на ноль:
>>> 100 / 0 Traceback (most recent call last): File "", line 1, in 100 / 0 ZeroDivisionError: division by zero
В данном случае интерпретатор сообщил нам об исключении ZeroDivisionError – делении на ноль.
Traceback
В большой программе исключения часто возникают внутри. Чтобы упростить программисту понимание ошибки и причины такого поведения Python предлагает Traceback или в сленге – трэйс. Каждое исключение содержит краткую информацию, но при этом полную, информацию о месте появления ошибки. По трэйсу найти и исправить ошибку становится проще.
Рассмотрим такой пример:
Traceback (most recent call last): File "/home/username/Develop/test/app.py", line 862, in _handle return route.call(**args) File "/home/username/Develop/test/app.py", line 1729, in wrapper rv = callback(*a, **ka) File "/home/username/Develop/test/__init__.py", line 76, in wrapper body = callback(*args, **kwargs) File "/home/username/Develop/test/my_app.py", line 16, in index raise Exception('test exception')
В данном примере чётко видно, какой путь исполнения у программы. Смотрим снизу вверх и по шагам понимаем, как же мы докатились до такого исключения.
Рассмотрим какие ещё встречаются комментарии к исключениям:
>>> 2 + '1' Traceback (most recent call last): File "", line 1, in 2 + '1' TypeError: unsupported operand type(s) for +: 'int' and 'str'
В данном примере при попытке сложить целое число и строку мы получаем исключение TypeError. В описании сразу же становится ясно, что же мы не так написали.
>>> int('qwerty') Traceback (most recent call last): File "", line 1, in int('qwerty') ValueError: invalid literal for int() with base 10: 'qwerty'
Приведение строчки к целому числу приводит к исключению ValueError.
В трэйсе этих двух примеров можно прочесть, что в таком-то файле на такой-то строчке есть ошибки.
На этом список встроенных исключений не заканчивается, в следующем разделе рассмотрены основные исключения и причины их возникновения.
Иерархия исключений
Исключение, которое вы не увидите при выполнении кода – это BaseException – базовое исключение, от которого берут начало остальные.
В иерархии исключений две основные группы:
- Системные исключения и ошибки
- Обыкновенные исключения
Если обработку первых лучше не делать (если и делать, то надо четко понимать для чего), то обработку вторых целиком и полностью Python возлагает на плечи программиста.
К системным можно смело отнести:
- SystemExit – исключение, порождаемое функцией sys.exit при выходе из программы.
- KeyboardInterrupt – возникает при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
- GeneratorExit — возникает при вызове метода close объекта generator.
Остальные исключения – это «обыкновенные». Спектр уже готовых исключений велик.
Для Python2 иерархию исключений можно представить так:
Список исключений покрывает большой объем ситуаций и ошибок программиста. Если предупреждения (warning) только просят обратить внимание, то ошибки уже могут остановить исполнение программы.
В Python3 появились новые исключения и иерархия стала такова:
В целом заметно, что при создании Python3 добавлен блок новых исключений. Но даже этих почти 70 исключений не хватает при написании программ на языке Python.
Использование исключений
Мы рассмотрели что такое исключения, какие они бывают и как их анализировать. Но до сих пор явно не рассмотрели такую важную вещь, как их использование.
Начнем с обработки.
Обработка исключений
Давайте рассмотрим случай с делением на 0.
>>> a = 100 >>> b = 0 >>> c = a / b
Данный код приведет к исключению ZeroDivisionError. Чтобы этого не случилось, воспользуемся конструкцией
, например, так:
>>> try: ... a = 100 ... b = 0 ... c = a / b ... except ZeroDivisionError as e: ... print(e) ... division by zero
Если исполнить этот код, то на консоль будет выведена строка «integer division or modulo by zero«. Казалось бы, что толком ничего это нам не дало, ошибка все также есть. Однако в блок except можно поместить обработку.
Например, мы условились, что значение переменной c в случае ошибки деления равно -1. Тогда модифицируем код:
>>> try: ... a = 100 ... b = 0 ... c = a / b ... except ZeroDivisionError as e: ... c = -1 >>> c -1
Перед тем как идти дальше, рассмотрим ещё одну возможность.
Пускай у нас файл с данными в файловой системе, и необходимо его прочитать. В этом случае сразу же всплывают несколько исключительных ситуаций, такие как: нет файла, файл битый, файл пустой (по заданию мы знаем, что в нём данные) и другие.
Используя исключения, можно вот так решить эту задачу:
try: filepath = 'test_file.txt' with open(filepath, 'r') as fio: result = fio.readlines() if not result: raise Exception("File is empty") except IOError as e: result = [] except Exception as e: result = [] print(e)
В данном вымышленном коде новый ход – перехват нескольких видов исключений. Когда исключение брошено, оно сравнивается сверху вниз с каждым типом, пока не найдено совпадение. Если совпадения нет, то исключение пойдет наверх по цепочке исполнения кода.
Если обработка для разных типов исключений одинакова, то уменьшить количество кода становится не проблемой:
try: your_code except (IOError, Exception) as e: print(e)
Вызов исключений
При работе с исключениями программист тратит большую часть времени на обработку, но при этом возникают ситуации, когда исключениями надо и бросать в других.
На сленге программистов «бросить исключение» означает написать код, который при исполнении будет инициировать исключительную ситуацию.
Например, функция, которая решает квадратное уравнение. Вы условились, что корни только вещественные, тогда в случае комплексных корней стоит бросить исключение.
Чтобы бросить исключение необходимо воспользоваться raise
Пример:
raise IOError("текст исключения")
где IOError это класс исключения.
Если при обработке исключения вы желаете пробросить его ещё выше, то следует написать такой код:
try: your_code except Exception as e: raise
Собственные исключения
При написании собственных программ разумное желание добавить выразительности коду, а так же обратить внимание других программистов на особые исключительные ситуации. Для решения этой задачи стоит использовать собственные исключения.
В минимальном исполнении необходимо наследоваться от какого-нибудь класса в иерархии исключений. Например так:
class MyException(Exception): pass
Тогда можно бросить своё исключение:
raise MyException(Exception)
Легко заметить, мы создаем класс, а значит всё, что мы знаем о классах, справедливо и для исключений. Можно завести переменные и делать их обработку.
Как правило, исключения это очень маленькие классы. Они должны выполняться максимально быстро.
Дополнение: Полная форма try..except
Форма try...except
не полная, полной же является try..except..else..finally
.
Применение полной конструкции может заметно упростить код, а также сделать его более безопасным.
Представим, что в программе происходит чтение файла и необходимо убедиться, что объект файла был корректно закрыт и что не возникло никакого исключения. Этого можно достичь с применением блока finally.
Иными словами, finally выполняет блок инструкций в любом случае, было ли исключение, или нет. А инструкция else выполняется в том случае, если исключения не было.
В целом, использование полной формы таково:
try: исполяем какой-то код except Exception as e: обработка исключения else: код, который будет исполнен в случае, когда не возникает исключения finally: код, который гарантированно будет исполнен последним (всегда исполняется)
Выводы
В уроке рассмотрены вопросы связанные с исключениями:
- Что такое исключение
- Какие типы исключений присутствуют в языке
- Как обрабатывать исключения
- Как вызвать исключения
- Как создавать собственные исключения
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты.
except и обработка разных типов исключений
Последнее обновление: 30.01.2022
Встроенные типы исключений
В примере выше обрабатывались сразу все исключения, которые могут возникнуть в коде. Однако мы можем конкретизировать тип обрабатываемого исключения, указав его после слова except:
try: number = int(input("Введите число: ")) print("Введенное число:", number) except ValueError: print("Преобразование прошло неудачно") print("Завершение программы")
В данном случае блок execpt обрабатывает только исключения типа ValueError, которые могут возникнут при неудачном преобразовании строки в число.
В Python есть следующие базовые типы исключений:
BaseException: базовый тип для всех встроенных исключений
Exception: базовый тип, который обычно применяется для создания своих типов исключений
ArithmeticError: базовый тип для исключений, связанных с арифметическими операциями (OverflowError, ZeroDivisionError, FloatingPointError).
BufferError: тип исключения, которое возникает при невозможности выполнить операцию с буффером
LookupError: базовый тип для исключений, которое возникают при обращении в коллекциях по некорректному ключу или индексу (например, IndexError, KeyError)
От этих классов наследуются все конкретные типы исключений. В Python обладает довольно большим списком встроенных исключений. Весь этот список можно посмотреть в документации. Перечислю только некоторые наиболее часто встречающиеся:
IndexError: исключение возникает, если индекс при обращении к элементу коллекции находится вне допустимого диапазона
KeyError: возникает, если в словаре отсутствует ключ, по которому происходит обращение к элементу словаря.
OverflowError: возникает, если результат арифметической операции не может быть представлен текущим числовым типом (обычно типом float).
RecursionError: возникает, если превышена допустимая глубина рекурсии.
TypeError: возникает, если операция или функция применяется к значению недопустимого типа.
ValueError: возникает, если операция или функция получают объект корректного типа с некорректным значением.
ZeroDivisionError: возникает при делении на ноль.
NotImplementedError: тип исключения для указания, что какие-то методы класса не реализованы
ModuleNotFoundError: возникает при при невозможности найти модуль при его импорте директивой
import
OSError: тип исключений, которые генерируются при возникновении ошибок системы (например, невозможно найти файл, память диска заполнена и т.д.)
И если ситуация такова, что в программе могут быть сгенерированы различные типы исключений, то мы можем их обработать по отдельности, используя дополнительные выражения except. И при возникновении исключения Python будет искать нужный блок except, который обрабатывает данный тип исключения:
try: number1 = int(input("Введите первое число: ")) number2 = int(input("Введите второе число: ")) print("Результат деления:", number1/number2) except ValueError: print("Преобразование прошло неудачно") except ZeroDivisionError: print("Попытка деления числа на ноль") except BaseException: print("Общее исключение") print("Завершение программы")
Если возникнет исключение в результате преобразования строки в число, то оно будет обработано блоком except ValueError
.
Если же второе число будет равно нулю, то есть будет деление на ноль, тогда возникнет исключение ZeroDivisionError, и оно будет обработано блоком
except ZeroDivisionError
.
Тип BaseException представляет общее исключение, под которое попадают все исключительные ситуации. Поэтому в данном случае
любое исключение, которое не представляет тип ValueError или ZeroDivisionError, будет обработано в блоке except BaseException:
.
Однако, если в программе возникает исключение типа, для которого нет соответствующего блока except
, то программа не сможет найти соответствующий блок except и
сгенерирует исключение. Например, в следующем случае:
try: number1 = int(input("Введите первое число: ")) number2 = int(input("Введите второе число: ")) print("Результат деления:", number1/number2) except ZeroDivisionError: print("Попытка деления числа на ноль") print("Завершение программы")
Здесь предусмотрена обработка деления на ноль с помощью блока except ZeroDivisionError
. Однако если пользователь вместо числа введет некорвертиуремую в число в строку, то
возникнет исключение типа ValueError, для которого нет соответствующего блока except. И поэтому программа аварийно завершит свое выполнение.
Python позволяет в одном блоке except обрабатывать сразу несколько типов исключений. В этом случае все типы исключения передаются в скобках:
try: number1 = int(input("Введите первое число: ")) number2 = int(input("Введите второе число: ")) print("Результат деления:", number1/number2) except (ZeroDivisionError, ValueError): # обработка двух типов исключений - ZeroDivisionError и ValueError print("Попытка деления числа на ноль или некорректный ввод") print("Завершение программы")
Получение информации об исключении
С помощью оператора as мы можем передать всю информацию об исключении в переменную, которую затем можно использовать в блоке except:
try: number = int(input("Введите число: ")) print("Введенное число:", number) except ValueError as e: print("Сведения об исключении", e) print("Завершение программы")
Пример некорректного ввода:
Введите число: fdsf Сведения об исключении invalid literal for int() with base 10: 'fdsf' Завершение программы
НазадСодержаниеВперед
errno — Стандартные системные символы errno — Документация Python 3.
11.2 Этот модуль предоставляет стандартные системные символы errno
. Значение каждого
символ — соответствующее целочисленное значение. Названия и описания есть
заимствован из linux/include/errno.h
, который должен быть
все включено.
- код ошибки
Словарь, обеспечивающий сопоставление значения errno с именем строки в базовая система. Например,
errno.errorcode[errno.EPERM]
сопоставляется с'ЭПЕРМ'
.
Чтобы преобразовать числовой код ошибки в сообщение об ошибке, используйте os.strerror()
.
Из следующего списка символы, которые не используются на текущей платформе, не
определяется модулем. Конкретный список определенных символов доступен как код_ошибки.keys()
. Доступные символы могут включать:
- номер ошибки.EPERM
Операция не разрешена. Эта ошибка сопоставляется с исключением
Ошибка разрешения
.
- ошибка.ENOENT
Нет такого файла или каталога. Эта ошибка сопоставляется с исключением
FileNotFoundError
.
- номер ошибки.ESRCH
Нет такого процесса. Эта ошибка сопоставляется с исключением
ProcessLookupError
.
- номер ошибки.EINTR
Прерванный системный вызов. Эта ошибка сопоставляется с исключением
Прерванная ошибка
.
- номер ошибки.EIO
Ошибка ввода/вывода
- ошибка ENXIO
Нет такого устройства или адреса
- номер ошибки.E2BIG
Список аргументов слишком длинный
- ошибка.ENOEXEC
Ошибка формата Exec
- номер ошибки.EBADF
Неверный номер файла
- errno.ECHILD
Нет дочерних процессов. Эта ошибка сопоставляется с исключением
Ошибка дочернего процесса
.
- ошибка.EAGAIN
Попробуйте еще раз. Эта ошибка сопоставляется с исключением
BlockingIOError
.
- номер ошибки.ENOMEM
Недостаточно памяти
- ошибка.EACCES
Отказано в доступе. Эта ошибка сопоставляется с исключением
Ошибка разрешения
.
- ошибка.EFAULT
Неверный адрес
- номер ошибки.ENOTBLK
Требуется блочное устройство
- номер ошибки.EBUSY
Устройство или ресурс занят
- ошибка.EEXIST
Файл существует. Эта ошибка сопоставляется с исключением
FileExistsError
.
- номер ошибки.EXDEV
Связь между устройствами
- ошибка. ENODEV
Нет такого устройства
- errno.ENOTDIR
Не каталог. Эта ошибка сопоставляется с исключением
NotADirectoryError
.
- номер ошибки.EISDIR
Каталог. Эта ошибка сопоставляется с исключением
IsADirectoryError
.
- ошибка.EINVAL
Неверный аргумент
- ошибка.ENFILE
Переполнение таблицы файлов
- ошибка.EMFILE
Слишком много открытых файлов
- ошибка.ENOTTY
Не пишущая машинка
- ошибка.ETXTBSY
Текстовый файл занят
- номер ошибки.EFBIG
Файл слишком большой
- номер ошибки.ENOSPC
На устройстве не осталось места
- ошибка.ESPIPE
Незаконный поиск
- ошибка. EROFS
Файловая система только для чтения
- номер ошибки.EMLINK
Слишком много ссылок
- номер ошибки.EPIPE
Сломанная труба. Эта ошибка сопоставляется с исключением
BrokenPipeError
.
- номер ошибки.EDOM
Математический аргумент вне области действия функции
- ошибка.ERANGE
Непредставимый математический результат
- номер ошибки.EDEADLK
Произойдет взаимоблокировка ресурса
- errno.ENAMETOOLONG
Имя файла слишком длинное
- номер ошибки.ENOLCK
Блокировки записей недоступны
- ошибка.ENOSYS
Функция не реализована
- ошибка.ENOTEMPTY
Каталог не пустой
- ошибка.ELOOP
Обнаружено слишком много символических ссылок
- errno. EWOULDBLOCK
Операция будет заблокирована. Эта ошибка сопоставляется с исключением
Блокировка IOError
.
- номер ошибки.ENOMSG
Нет сообщения нужного типа
- номер ошибки.EIDRM
Идентификатор удален
- ошибка.ECHRNG
Номер канала вне допустимого диапазона
- ошибка.EL2NSYNC
Уровень 2 не синхронизирован
- номер ошибки.EL3HLT
Уровень 3 остановлен
- номер ошибки.EL3RST
Сброс уровня 3
- номер ошибки.ELNRNG
Номер ссылки вне допустимого диапазона
- ошибка.EUNATCH
Драйвер протокола не подключен
- ошибка.ENOCSI
Структура CSI отсутствует
- номер ошибки.EL2HLT
Уровень 2 остановлен
- номер ошибки. EBADE
Неверный обмен
- номер ошибки.EBADR
Недопустимый дескриптор запроса
- ошибка.EXFULL
Полный обмен
- errno.ENOANO
Без анода
- номер ошибки EBADRQC
Неверный код запроса
- номер ошибки.EBADST
Неверный слот
- errno.EDEADLOCK
Ошибка блокировки файла
- номер ошибки.EBFONT
Неверный формат файла шрифта
- номер ошибки.ENOSTR
Устройство не является потоком
- errno.ENODATA
Нет данных
- ошибка.ETIME
Таймер истек
- номер ошибки.ENOSR
Вне потоков ресурсов
- номер ошибки.ENONET
Машина не в сети
- номер ошибки. ENOPKG
Пакет не установлен
- errno.REMOTE
Объект удален
- ошибка.ENOLINK
Связь разорвана
- номер ошибки.EADV
Ошибка объявления
- номер ошибки.ESRMNT
Ошибка запуска
- ошибка.COMM
Ошибка связи при отправке
- ошибка.EPROTO
Ошибка протокола
- errno.EMULTIHOP
Многоскачковая попытка
- номер ошибки.EDOTDOT
Специфическая ошибка RFS
- номер ошибки.EBADMSG
Не сообщение данных
- errno.EOVERFLOW
Слишком большое значение для определенного типа данных
- номер ошибки.ENOTUNIQ
Имя не уникально в сети
- номер ошибки. EBADFD
Файловый дескриптор в плохом состоянии
- errno.EREMCHG
Удаленный адрес изменен
- номер ошибки.ELIBACC
Не удается получить доступ к необходимой общей библиотеке
- номер ошибки.ELIBBAD
Доступ к поврежденной общей библиотеке
- номер ошибки.ELIBSCN
Раздел .lib в a.out поврежден
- номер ошибки.ELIBMAX
Попытка связать слишком много общих библиотек
- ошибка.ELIBEXEC
Невозможно запустить общую библиотеку напрямую
- номер ошибки.EILSEQ
Недопустимая последовательность байтов
- errno.ERRESTART
Прерванный системный вызов следует перезапустить
- ошибка.ESTRPPIPE
Ошибка канала потоков
- ошибка. EUSERS
Слишком много пользователей
- ошибка.ENOTSOCK
Работа сокета без сокета
- errno.EDESTADDRREQ
Требуется адрес назначения
- ошибка.EMSGSIZE
Сообщение слишком длинное
- errno.EPROTOTYPE
Неверный тип протокола для сокета
- errno.ENOPROTOOPT
Протокол недоступен
- ошибка.EPROTONOSUPPORT
Протокол не поддерживается
- ошибка ESOCKTNOSUPPORT
Тип сокета не поддерживается
- ошибка.EOPNOTSUPP
Операция не поддерживается на конечной точке транспорта
- номер ошибки.EPFNOSUPPORT
Семейство протоколов не поддерживается
- ошибка.EAFNOSUPPORT
Семейство адресов не поддерживается протоколом
- ошибка. EADDRINUSE
Адрес уже используется
- errno.EADDRNOTAVAIL
Невозможно назначить запрошенный адрес
- ошибка.ENETDOWN
Сеть не работает
- errno.ENETUNREACH
Сеть недоступна
- ошибка ENETRESET
Сетевое соединение разорвано из-за сброса
- errno.ECONNABORTED
Программное обеспечение вызвало разрыв соединения. Эта ошибка сопоставляется с исключение
ConnectionAbortedError
.
- errno.ECONNRESET
Соединение сброшено узлом. Эта ошибка сопоставляется с исключением
ConnectionResetError
.
- ошибка.ENOBUFS
Нет свободного места в буфере
- номер ошибки EISCONN
Конечная точка транспорта уже подключена
- номер ошибки. ENOTCONN
Конечная точка транспорта не подключена
- errno.ESHUTDOWN
Не удается отправить после завершения работы конечной точки транспорта. Эта ошибка отображается к исключению
BrokenPipeError
.
- errno.ETOOMANYREFS
Слишком много ссылок: невозможно соединить
- ошибка.ETIMEDOUT
Время ожидания соединения истекло. Эта ошибка сопоставляется с исключением
Ошибка тайм-аута
.
- errno.ECONREFUSED
В соединении отказано. Эта ошибка сопоставляется с исключением
ConnectionRefusedError
.
- ошибка.EHOSTDOWN
Хост недоступен
- ошибка.EHOSTUNREACH
Нет маршрута к хосту
- errno.EALREADY
Операция уже выполняется. Эта ошибка сопоставляется с исключение
BlockingIOError
.
- ошибка.EINPROGRESS
Выполняется операция. Эта ошибка сопоставляется с исключением
Блокировка IOError
.
- errno.ESTALE
Устаревший дескриптор файла NFS
- ошибка.EUCLEAN
Требуется очистка конструкции
- номер ошибки.ENOTNAM
Не является файлом именованного типа XENIX
- errno.ENAVAIL
Нет доступных семафоров XENIX
- номер ошибки.EISNAM
Является файлом именованного типа
- errno.EREMOTEIO
Ошибка удаленного ввода/вывода
- ошибка.EDQUOT
Превышена квота
- ошибка.EQFULL
Очередь вывода интерфейса заполнена
Новое в версии 3.11.
- errno.ENOTCAPABLE
Возможностей недостаточно. Эта ошибка сопоставляется с исключением
Ошибка разрешения
.Наличие: WASI, FreeBSD
Новое в версии 3.11.1.
предупреждений — Управление предупреждениями — Документация Python 3.11.2
Исходный код: Lib/warnings.py
Предупреждающие сообщения обычно выдаются в ситуациях, когда полезно пользователь некоторого условия в программе, где это условие (обычно) не ордер на возбуждение исключения и завершение программы. Например, один может захотеть выдать предупреждение, когда программа использует устаревший модуль.
Программисты Python выдают предупреждения, вызывая функцию warn()
, определенную
в этом модуле. (программисты на C используют PyErr_WarnEx()
; видеть
Подробности об обработке исключений).
Предупреждающие сообщения обычно записываются в sys.stderr
, но их расположение
можно гибко менять, от игнорирования всех предупреждений до превращения их в
исключения. Расположение предупреждений может различаться в зависимости от категории предупреждения, текста предупреждающего сообщения и исходного расположения, в котором оно находится.
выпущен. Повторы конкретного предупреждения для одного и того же источника запрещены.
обычно подавляется.
Управление предупреждениями состоит из двух стадий: во-первых, каждый раз, когда выдается предупреждение, делается определение, следует ли выдавать сообщение или нет; далее, если сообщение должно быть выдано, оно форматируется и печатается с использованием настраиваемого пользователем хука.
Решение о том, выдавать ли предупреждающее сообщение, контролируется
фильтр предупреждений, представляющий собой последовательность соответствующих правил и действий. Правила могут быть
добавлен в фильтр, вызвав filterwarnings()
и сброшен по умолчанию
состояние, вызвав resetwarnings()
.
Печать предупреждающих сообщений выполняется вызовом showwarning()
, который
может быть переопределен; реализация этой функции по умолчанию форматирует
сообщение, вызвав formatwarning()
, который также доступен для использования
пользовательские реализации.
См. также
logging.captureWarnings()
позволяет обрабатывать все предупреждения с помощью
стандартная инфраструктура регистрации.
Категории предупреждений
Существует ряд встроенных исключений, представляющих категории предупреждений. Эта категоризация полезна для возможности фильтрации групп предупреждений.
Хотя технически это встроенные исключения, они задокументированы здесь, потому что концептуально они относятся к механизму предупреждений.
Код пользователя может определять дополнительные категории предупреждений путем подкласса одного из
стандартные категории предупреждений. Категория предупреждений всегда должна быть подклассом
класс Предупреждение
.
В настоящее время определены следующие классы категорий предупреждений:
Класс | Описание |
---|---|
| Это базовый класс всех предупреждений. классы категорий. Это подкласс |
| Категория по умолчанию для |
| Базовая категория для предупреждений об устаревших
функции, когда эти предупреждения предназначены для
другие разработчики Python (по умолчанию игнорируются,
если это не вызвано кодом в |
| Базовая категория для предупреждений о сомнительных синтаксические особенности. |
| Базовая категория для предупреждений о сомнительных особенности выполнения. |
| Базовая категория для предупреждений об устаревших функции, когда эти предупреждения предназначены для конечные пользователи приложений, написанных на Питон. |
| Базовая категория для предупреждений о функциях который будет устарел в будущем (игнорируется по умолчанию). |
| Базовая категория для предупреждений, срабатывающих во время процесс импорта модуля (игнорируется по умолчанию). |
| Базовая категория для предупреждений, связанных с Юникод. |
| Базовая категория для предупреждений, связанных с |
| Базовая категория для предупреждений, связанных с использование ресурсов (по умолчанию игнорируется). |
Изменено в версии 3.7: Ранее Предупреждение об устаревании
и FutureWarning
были
различаются в зависимости от того, удалялась ли функция полностью или
изменение своего поведения. Теперь их различают по их
предполагаемая аудитория и то, как они обрабатываются предупреждениями по умолчанию
фильтры.
Фильтр предупреждений
Фильтр предупреждений определяет, будут ли предупреждения игнорироваться, отображаться или в ошибки (возбуждение исключения).
Концептуально фильтр предупреждений поддерживает упорядоченный список фильтров. Характеристики; любое конкретное предупреждение сопоставляется с каждым фильтром спецификацию в списке по очереди, пока не будет найдено совпадение; фильтр определяет диспозиция матча. Каждая запись представляет собой кортеж вида ( действие , сообщение , категория , модуль , линейно ), где:
действие является одной из следующих строк:
Значение
Распоряжение
"по умолчанию"
вывести первое совпадение предупреждения для каждой локации (модуль + номер строки), где выдается предупреждение
"ошибка"
превратить соответствующие предупреждения в исключения
"игнорировать"
никогда не печатать соответствующие предупреждения
"всегда"
всегда печатать соответствующие предупреждения
"модуль"
вывести первое совпадение предупреждения для каждого модуля, где предупреждение выдается (независимо от номера строки)
"один раз"
печатать только первое совпадение предупреждения, независимо от местонахождения
сообщение — это строка, содержащая регулярное выражение, начало которого предупреждающее сообщение должно совпадать без учета регистра. В
-W
иPYTHONWARNINGS
, сообщение — буквальная строка, которая является началом предупреждающее сообщение должно содержать (без учета регистра), игнорируя любые пробелы в начало или конец сообщение .категория — это класс (подкласс
Предупреждение
), для которого предупреждение категория должна быть подклассом, чтобы соответствовать.модуль представляет собой строку, содержащую регулярное выражение, которое является началом полное имя модуля должно совпадать с учетом регистра. В
-W
иPYTHONWARNINGS
, модуль — это литеральная строка, которую полное имя модуля должно быть равно (с учетом регистра), игнорируя любые пробел в начале или в конце модуль .lineno — целое число, которое должно соответствовать номеру строки, в которой появилось предупреждение. match или
0
для соответствия всем номерам строк.
Поскольку класс Warning
является производным от встроенного Exception
class, чтобы превратить предупреждение в ошибку, мы просто поднимаем категорию (сообщение)
.
Если сообщается о предупреждении, которое не соответствует ни одному зарегистрированному фильтру, то применяется действие «по умолчанию» (отсюда и его название).
Описание фильтров предупреждений
Фильтр предупреждений инициализируется параметрами -W
, переданными в Python
командная строка интерпретатора и переменная среды PYTHONWARNINGS
.
Интерпретатор сохраняет аргументы для всех предоставленных записей без
интерпретация в sys.warnoptions
; модуль warnings
анализирует эти
при первом импорте (недопустимые параметры игнорируются, после печати
сообщение на sys.stderr
).
Фильтры отдельных предупреждений задаются в виде последовательности полей, разделенных двоеточия:
действие: сообщение: категория: модуль: строка
Значение каждого из этих полей соответствует описанию в разделе Фильтр предупреждений. При перечислении нескольких фильтров в одной строке (например, PYTHONWARNINGS
), отдельные фильтры разделяются запятыми и
фильтры, перечисленные ниже, имеют приоритет над теми, которые перечислены перед ними (как
они применяются слева направо, а самые последние примененные фильтры занимают
приоритет перед предыдущими).
Обычно используемые фильтры предупреждений применяются либо ко всем предупреждениям, либо к предупреждениям в конкретной категории или предупреждений, выдаваемых определенными модулями или пакетами. Некоторые примеры:
default # Показать все предупреждения (даже игнорируемые по умолчанию) ignore # Игнорировать все предупреждения error # Преобразовать все предупреждения в ошибки error::ResourceWarning # Рассматривать сообщения ResourceWarning как ошибки default::DeprecationWarning # Показать сообщения DeprecationWarning ignore,default:::mymodule # Сообщать только о предупреждениях, вызванных "mymodule" error:::mymodule # Преобразование предупреждений в ошибки в "mymodule"
Фильтр предупреждений по умолчанию
По умолчанию Python устанавливает несколько фильтров предупреждений, которые можно переопределить с помощью
параметр командной строки -W
, среда PYTHONWARNINGS
переменная и вызывает filterwarnings()
.
В сборках обычных выпусков фильтр предупреждений по умолчанию имеет следующие записи. (в порядке старшинства):
по умолчанию::DeprecationWarning:__main__ игнорировать::DeprecationWarning ignore::PendingDeprecationWarning игнорировать:: ИмпортВарнинг игнорировать:: ResourceWarning
В отладочной сборке список фильтров предупреждений по умолчанию пуст.
Изменено в версии 3.2: DeprecationWarning
теперь игнорируется по умолчанию в дополнение к PendingDeprecationWarning
.
Изменено в версии 3.7: DeprecationWarning
снова отображается по умолчанию при срабатывании
напрямую по коду __main__
.
Изменено в версии 3.7: BytesWarning
больше не отображается в списке фильтров по умолчанию и
вместо этого настроен через sys.warnoptions
, когда указано -b
дважды.
Переопределение фильтра по умолчанию
Разработчики приложений, написанных на Python, могут захотеть скрыть все уровни Python
предупреждения от своих пользователей по умолчанию и отображать их только при запуске тестов
или иным образом работает над приложением. Атрибут sys.warnoptions
используется для передачи настроек фильтра интерпретатору, может использоваться в качестве маркера для
указать, следует ли отключать предупреждения:
система импорта если не sys.warnoptions: предупреждения об импорте предупреждения.simplefilter("игнорировать")
Разработчикам тестовых исполнителей для кода Python рекомендуется вместо этого убедиться, что все предупреждения отображаются по умолчанию для тестируемого кода с использованием кода как:
система импорта если не sys.warnoptions: импорт ОС, предупреждения warnings.simplefilter("default") # Изменить фильтр в этом процессе os.environ["PYTHONWARNINGS"] = "default" # Также влияет на подпроцессы
Наконец, разработчики интерактивных оболочек, выполняющих пользовательский код в пространстве имен.
кроме __main__
рекомендуется убедиться, что DeprecationWarning
сообщения становятся видимыми по умолчанию с помощью кода, подобного следующему (где user_ns
— это модуль, используемый для выполнения кода, введенного в интерактивном режиме):
предупреждения об импорте warnings. filterwarnings("по умолчанию", category=Предупреждение об устаревании, модуль = user_ns.get ("__ имя__"))
Временное подавление предупреждений
Если вы используете код, который, как вы знаете, вызовет предупреждение, например устаревшее
функции, но не хотят видеть предупреждение (даже если предупреждения были
явно настраивается через командную строку), то есть возможность подавить
предупреждение с использованием менеджера контекста catch_warnings
:
предупреждения об импорте защита fxn(): warnings.warn("устарело", DeprecationWarning) с предупреждениями.catch_warnings(): предупреждения.simplefilter("игнорировать") fxn()
В менеджере контекста все предупреждения будут просто игнорироваться. Этот
позволяет вам использовать заведомо устаревший код без необходимости видеть предупреждение во время
не подавлять предупреждение для другого кода, который может не знать о его использовании
устаревшего кода. Примечание: это может быть гарантировано только в однопоточном
приложение. Если два или более потока используют контекст catch_warnings
менеджер в то же время, поведение не определено.
Предупреждения тестирования
Чтобы протестировать предупреждения, вызванные кодом, используйте catch_warnings
контекст
менеджер. С его помощью вы можете временно изменить фильтр предупреждений, чтобы облегчить
ваше тестирование. Например, сделайте следующее, чтобы зафиксировать все поднятые предупреждения в
чек:
предупреждения об импорте защита fxn(): warnings.warn("устарело", DeprecationWarning) с warnings.catch_warnings(record=True) как w: # Сделать так, чтобы все предупреждения всегда срабатывали. предупреждения.simplefilter("всегда") # Вывести предупреждение. fxn() # Проверить некоторые вещи утверждать len(w) == 1 утверждать issubclass(w[-1].category, DeprecationWarning) утверждать "устаревшее" в строке (w[-1]. message)
Можно также сделать все предупреждения исключениями, используя ошибку
вместо всегда
. Одна вещь, о которой следует помнить, это то, что если предупреждение уже было
поднял из-за раз
/ правило по умолчанию
, то без разницы какие фильтры стоят
установите, что предупреждение больше не будет отображаться, если только реестр предупреждений, связанный с
предупреждение было удалено.
После выхода из диспетчера контекста фильтр предупреждений возвращается в исходное состояние.
когда был введен контекст. Это предотвращает изменение предупреждений тестами.
фильтруют неожиданным образом между тестами и приводят к неопределенным тестам
Результаты. функция showwarning()
в модуле также восстанавливается до
его первоначальное значение. Примечание: это может быть гарантировано только в однопоточном
приложение. Если два или более потока используют контекст catch_warnings
менеджер в то же время, поведение не определено.
При тестировании нескольких операций, вызывающих одинаковые предупреждения, важно протестировать их таким образом, чтобы подтвердить, что каждая операция поднимает новое предупреждение (например, настроить предупреждения как исключения и проверить операции вызывают исключения, убедитесь, что длина списка предупреждений продолжает увеличиваться после каждой операции, либо удалить предыдущую записи из списка предупреждений перед каждой новой операцией).
Обновление кода для новых версий зависимостей
Категории предупреждений, которые в первую очередь представляют интерес для разработчиков Python (скорее чем конечные пользователи приложений, написанных на Python) по умолчанию игнорируются.
Примечательно, что этот список «игнорируется по умолчанию» включает DeprecationWarning
(для каждого модуля, кроме __main__
), что означает, что разработчики должны убедиться
для тестирования своего кода с обычно игнорируемыми предупреждениями, сделанными видимыми, чтобы
получать своевременные уведомления о будущих критических изменениях API (будь то в
стандартная библиотека или сторонние пакеты).
В идеальном случае код будет иметь подходящий набор тестов, а программа запуска тестов
позаботится о неявном включении всех предупреждений при запуске тестов
(это делает средство запуска тестов, предоставляемое модулем unittest
).
В менее идеальных случаях приложения могут быть проверены на использование устаревших
интерфейсы, передав -Wd
интерпретатору Python (это
сокращение для -W по умолчанию
) или установка PYTHONWARNINGS=
по умолчанию в
окружающая среда. Это включает обработку по умолчанию для всех предупреждений, включая
которые игнорируются по умолчанию. Чтобы изменить действие, предпринимаемое для обнаруженных
предупреждения вы можете изменить, какой аргумент передается на -W
(например, -W ошибка
). См. флаг -W
для получения более подробной информации о том, что
возможный.
Доступные функции
- warnings.warn( сообщение , категория=Нет , уровень стека=1 , источник=Нет )
Выдать предупреждение или, возможно, проигнорировать его или вызвать исключение. Категория аргумент, если он задан, должен быть классом категории предупреждений; это по умолчанию
UserWarning
. В качестве альтернативы 9Сообщение 1291 может быть экземпляромWarning
, в этом случае категория будет проигнорирована и будет использоватьсяmessage.__class__
. В этом случае текст сообщения будетstr(message)
. Эта функция вызывает исключение, если конкретное выданное предупреждение изменено на ошибку фильтр предупреждений. Аргумент stacklevel может использоваться оболочкой функции, написанные на Python, например:дерекламация (сообщение): warnings.warn (сообщение, предупреждение об устаревании, уровень стека = 2)
Это заставляет предупреждение ссылаться на вызывающую функцию
deprecation()
, а не на источник самогоdeprecation()
(поскольку последний нарушил бы цель предупреждающего сообщения).источник , если указан, это уничтоженный объект, испустивший
Предупреждение о ресурсе
.Изменено в версии 3.6: Добавлен параметр source .
- warnings.warn_explicit( сообщение , категория , имя файла , lineno , модуль=нет , реестр=нет , module_globals=нет , источник=нет )
Это низкоуровневый интерфейс для функций
warn()
, переходящий в явно сообщение, категорию, имя файла и номер строки, и, возможно, имя модуля и реестр (который должен быть__warningregistry__
словарь модуля). Имя модуля по умолчанию равно имени файла с.py
раздели; если реестр не передается, предупреждение никогда не подавляется. сообщение должно быть строкой и категорией подклассомПредупреждение
или Сообщение может быть экземпляромWarning
, и в этом случае категория будет игнорируется.module_globals , если указано, должно быть глобальным пространством имен, используемым кодом за что вынесено предупреждение. (Этот аргумент используется для поддержки отображения источник для модулей, найденных в zip-файлах или другом импорте, не относящемся к файловой системе источники).
источник , если указан, это уничтоженный объект, испустивший
Предупреждение о ресурсе
.Изменено в версии 3.6: добавлен параметр источника .
- warnings.showwarning( сообщение , категория , имя файла , lineno , file=None , line=None )
Записать предупреждение в файл. Реализация по умолчанию вызывает
formatwarning(сообщение, категория, имя файла, номер строки, строка)
и пишет результирующая строка файл , который по умолчанию равенsys.stderr
. Вы можете заменить эту функцию с любым вызываемым, назначивwarnings.showwarning
. строка — это строка исходного кода, которая должна быть включена в предупреждение сообщение; если строка не указана,showwarning()
будет попробуйте прочитать строку, указанную имя файла и lineno .
- предупреждения.formatwarning( сообщение , категория , имя файла , lineno , строка=нет )
Отформатировать предупреждение стандартным способом. Это возвращает строку, которая может содержать встроенные символы новой строки и заканчиваются новой строкой. строка — это строка исходного кода для быть включенным в предупреждающее сообщение; если строка не указана,
formatwarning()
попытается прочитать строку, указанную именем файла и линейно .
- warnings.filterwarnings( action , message=» , category=Warning , module=» , lineno=0 , append=False )
Вставить запись в список спецификаций фильтра предупреждений. Запись вставляется впереди по умолчанию; если добавить верно, оно вставляется в конце. Это проверяет типы аргументы, компилирует сообщения и модуль регулярные выражения, и вставляет их как кортеж в список фильтров предупреждений. Записи ближе к в начале списка переопределяют записи, расположенные дальше в списке, если оба соответствуют конкретное предупреждение. Пропущенные аргументы по умолчанию соответствуют значению, которое соответствует все.
- warnings.simplefilter( action , category=Warning , lineno=0 , append=False )
Вставить простую запись в список спецификаций фильтра предупреждений. Смысл параметров функции такой же, как для
filterwarnings()
, но регулярные выражения не нужны в качестве фильтра вставка всегда соответствует любому сообщению в любом модуле, если категория и номер строки совпадает.
- предупреждения.resetwarnings()
Сбросить фильтр предупреждений. Это отменяет эффект всех предыдущих вызовов
filterwarnings()
, включая параметры командной строки-W
и вызываетsimplefilter()
.
Доступные менеджеры контекста
- класс warnings. catch_warnings( * , запись=ложь , модуль=нет , действие=нет , категория = предупреждение , lineno = 0 , добавление = ложь )
Менеджер контекста, который копирует и при выходе восстанавливает фильтр предупреждений и функция
showwarning()
. Если аргумент записи равенFalse
(по умолчанию), менеджер контекста возвращаетNone
при входе. Если запись равнаTrue
, список возвращается, который постепенно заполняется объектами, как их видит пользовательскийпоказать предупреждение()
(которая также подавляет вывод наsys.stdout
). Каждый объект в списке имеет атрибуты с теми же именами, что и аргументы дляпоказать предупреждение()
.Аргумент модуля принимает модуль, который будет использоваться вместо модуль возвращается при импорте предупреждений