warnings — Управление предупреждениями
Исходный код: Lib/warnings.py
Предупреждения обычно выдаются в ситуациях, когда полезно сообщить пользователю о некотором условии в программе, которое (как правило) не требует возбуждения исключения и завершения программы. Например, можно выдавать предупреждение, когда программа использует устаревший модуль.
Программисты на Python выдают предупреждения, вызывая функцию warn(), определённую в этом модуле. (Программисты на C используют PyErr_WarnEx(); подробности см. в разделе Обработка исключений).
Предупреждения обычно записываются в sys.stderr, но их обработку можно гибко изменить: от игнорирования всех предупреждений до преобразования их в исключения. Обработка предупреждений может зависеть от категории предупреждения, текста предупреждения и места в исходном коде, где оно выдано. Повторные предупреждения в одном и том же месте исходного кода обычно подавляются.
Управление предупреждениями состоит из двух этапов: сначала при каждом выдаче предупреждения определяется, следует ли показывать сообщение; затем, если сообщение нужно показать, оно форматируется и выводится с помощью настраиваемой пользователем функции-перехватчика.
Решение о том, следует ли показывать предупреждение, контролируется фильтром предупреждений, который представляет собой последовательность правил сопоставления и действий. Правила можно добавлять в фильтр вызовом filterwarnings(), а сбросить его до состояния по умолчанию — вызовом resetwarnings().
Вывод предупреждений выполняется вызовом showwarning(), которую можно переопределить; реализация этой функции по умолчанию форматирует сообщение вызовом formatwarning(), доступной также для использования в пользовательских реализациях.
См. также
logging.captureWarnings() позволяет обрабатывать все предупреждения с помощью стандартной инфраструктуры журналирования.
Категории предупреждений
Существует ряд встроенных исключений, представляющих категории предупреждений. Такая категоризация позволяет фильтровать группы предупреждений.
Хотя технически это встроенные исключения, они описаны здесь, поскольку концептуально относятся к механизму предупреждений.
Пользовательский код может определять дополнительные категории предупреждений, создавая подклассы одной из стандартных категорий. Категория предупреждения всегда должна быть подклассом класса Warning.
В настоящее время определены следующие классы категорий предупреждений:
Класс | Описание |
|---|---|
Базовый класс для всех классов категорий предупреждений. Он является подклассом | |
Категория по умолчанию для | |
Базовая категория предупреждений об устаревших возможностях, предназначенных для других разработчиков Python (по умолчанию игнорируются, если не вызваны кодом в | |
Базовая категория предупреждений о сомнительных синтаксических конструкциях (обычно выдаются при компиляции исходного кода Python и поэтому могут не подавляться фильтрами времени выполнения). | |
Базовая категория предупреждений о сомнительных возможностях времени выполнения. | |
Базовая категория предупреждений об устаревших возможностях, предназначенных для конечных пользователей приложений, написанных на Python. | |
Базовая категория предупреждений о возможностях, которые будут объявлены устаревшими в будущем (по умолчанию игнорируются). | |
Базовая категория предупреждений, выдаваемых во время импорта модуля (по умолчанию игнорируются). | |
Базовая категория предупреждений, связанных с Unicode. | |
Базовая категория предупреждений, связанных с | |
Базовая категория предупреждений, связанных с использованием ресурсов (по умолчанию игнорируются). |
Изменено в версии 3.7: Ранее различие между DeprecationWarning и FutureWarning определялось тем, удалялась ли возможность полностью или менялось её поведение. Теперь различие определяется целевой аудиторией и тем, как эти предупреждения обрабатываются фильтрами предупреждений по умолчанию.
Фильтр предупреждений
Фильтр предупреждений определяет, будут ли предупреждения игнорироваться, отображаться или превращаться в ошибки (вызывать исключение).
Концептуально фильтр предупреждений содержит упорядоченный список спецификаций фильтров; каждое конкретное предупреждение последовательно сопоставляется со спецификациями из списка, пока не будет найдено совпадение; фильтр определяет способ обработки совпадения. Каждая запись — это кортеж вида (действие, сообщение, категория, модуль, номер_строки), где:
-
действие — одна из следующих строк:
Значение
Обработка
"default"вывести первое совпадающее предупреждение для каждого места (модуль + номер строки), в котором оно выдано
"error"преобразовать совпадающие предупреждения в исключения
"ignore"никогда не выводить совпадающие предупреждения
"always"всегда выводить совпадающие предупреждения
"module"вывести первое совпадающее предупреждение для каждого модуля, в котором оно выдано (независимо от номера строки)
"once"вывести только первое совпадающее предупреждение, независимо от места
-
сообщение — строка, содержащая регулярное выражение, которому должно соответствовать начало текста предупреждения без учёта регистра. В
-WиPYTHONWARNINGSсообщение — буквальная строка, которая должна содержаться в начале текста предупреждения (без учёта регистра); пробелы в начале и конце сообщения игнорируются. -
категория — класс (подкласс
Warning), подклассом которого должна быть категория предупреждения, чтобы совпадение было найдено. -
модуль — строка, содержащая регулярное выражение, которому должно соответствовать начало полного имени модуля с учётом регистра. В
-WиPYTHONWARNINGSмодуль — буквальная строка, которой должно полностью совпадать полное имя модуля (с учётом регистра); пробелы в начале и конце модуля игнорируются. -
номер_строки — целое число, которому должен соответствовать номер строки, где возникло предупреждение, или
0, чтобы совпадали все номера строк.
Поскольку класс Warning является производным от встроенного класса Exception, чтобы превратить предупреждение в ошибку, достаточно возбудить category(message).
Если выданное предупреждение не соответствует ни одному зарегистрированному фильтру, применяется действие «по умолчанию» (отсюда и его название).
Критерии подавления повторных предупреждений
Фильтры, подавляющие повторные предупреждения, используют следующие критерии, чтобы определить, считается ли предупреждение повторным:
-
"default": предупреждение считается повторным, только если значения (сообщение, категория, модуль, номер_строки) совпадают. -
"module": предупреждение считается повторным, если совпадают значения (сообщение, категория, модуль), а номер строки не учитывается. -
"once": предупреждение считается повторным, если совпадают значения (сообщение, категория), а модуль и номер строки не учитываются.
Описание фильтров предупреждений
Фильтр предупреждений инициализируется параметрами -W, переданными в командной строке интерпретатора Python, и переменной окружения PYTHONWARNINGS. Интерпретатор сохраняет аргументы всех переданных записей без обработки в sys.warnoptions; модуль warnings разбирает их при первом импорте (недопустимые параметры игнорируются после вывода сообщения в sys.stderr).
Отдельные фильтры предупреждений задаются последовательностью полей, разделённых двоеточиями:
action:message:category:module:line
Значение каждого из этих полей описано в разделе Фильтр предупреждений. Если в одной строке указано несколько фильтров (например, в PYTHONWARNINGS), отдельные фильтры разделяются запятыми, а фильтры, перечисленные позже, имеют приоритет над предыдущими (поскольку они применяются слева направо, и последние применённые фильтры имеют приоритет над более ранними).
Часто используемые фильтры предупреждений применяются ко всем предупреждениям, предупреждениям определённой категории или предупреждениям, выдаваемым определёнными модулями или пакетами. Примеры:
default # Show all warnings (even those ignored by default) ignore # Ignore all warnings error # Convert all warnings to errors error::ResourceWarning # Treat ResourceWarning messages as errors default::DeprecationWarning # Show DeprecationWarning messages ignore,default:::mymodule # Only report warnings triggered by "mymodule" error:::mymodule # Convert warnings to errors in "mymodule"
Фильтр предупреждений по умолчанию
По умолчанию Python устанавливает несколько фильтров предупреждений, которые можно переопределить параметром командной строки -W, переменной окружения PYTHONWARNINGS и вызовами filterwarnings().
В обычных сборках для выпуска фильтр предупреждений по умолчанию содержит следующие записи (в порядке приоритета):
default::DeprecationWarning:__main__ ignore::DeprecationWarning ignore::PendingDeprecationWarning ignore::ImportWarning ignore::ResourceWarning
В отладочной сборке список фильтров предупреждений по умолчанию пуст.
Изменено в версии 3.2: Теперь DeprecationWarning по умолчанию игнорируется наряду с PendingDeprecationWarning.
Изменено в версии 3.7: DeprecationWarning снова отображается по умолчанию, если предупреждение непосредственно вызвано кодом в __main__.
Изменено в версии 3.7: BytesWarning больше не входит в список фильтров по умолчанию; вместо этого его настройка выполняется через sys.warnoptions, если параметр -b указан дважды.
Переопределение фильтра по умолчанию
Разработчики приложений на Python могут захотеть по умолчанию скрыть от пользователей все предупреждения уровня Python и показывать их только при запуске тестов или другой работе над приложением. Атрибут sys.warnoptions, используемый для передачи конфигураций фильтров интерпретатору, можно применять как маркер, показывающий, следует ли отключить предупреждения:
import sys
if not sys.warnoptions:
import warnings
warnings.simplefilter("ignore")
Разработчикам средств запуска тестов для кода на Python рекомендуется вместо этого по умолчанию отображать все предупреждения для проверяемого кода, используя, например, такой код:
import sys
if not sys.warnoptions:
import os, warnings
warnings.simplefilter("default") # Change the filter in this process
os.environ["PYTHONWARNINGS"] = "default" # Also affect subprocesses
Наконец, разработчикам интерактивных оболочек, выполняющих пользовательский код в пространстве имён, отличном от __main__, рекомендуется по умолчанию сделать сообщения DeprecationWarning видимыми, используя, например, следующий код (где user_ns — модуль, используемый для выполнения кода, введённого в интерактивном режиме):
import warnings
warnings.filterwarnings("default", category=DeprecationWarning,
module=user_ns.get("__name__"))
Временное подавление предупреждений
Если вы используете код, который, как вам известно, выдаёт предупреждение, например устаревшую функцию, но не хотите видеть это предупреждение (даже если предупреждения были явно настроены через командную строку), его можно подавить с помощью менеджера контекста catch_warnings:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
Внутри менеджера контекста все предупреждения просто игнорируются. Это позволяет использовать заведомо устаревший код, не видя предупреждений, и при этом не подавлять предупреждения для другого кода, который может не знать об использовании устаревшего кода. Примечание: это гарантируется только в однопоточном приложении. Если два или более потоков одновременно используют менеджер контекста catch_warnings, поведение не определено.
Тестирование предупреждений
Для тестирования предупреждений, выдаваемых кодом, используйте менеджер контекста catch_warnings. С его помощью можно временно изменить фильтр предупреждений, чтобы упростить тестирование. Например, чтобы перехватить все выданные предупреждения для проверки, выполните следующее:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
Также можно преобразовать все предупреждения в исключения, используя error вместо always. Следует учитывать: если предупреждение уже было выдано из-за правила once/default, оно больше не появится независимо от установленных фильтров, пока не будет очищен реестр предупреждений, относящийся к этому предупреждению.
После выхода из менеджера контекста фильтр предупреждений восстанавливается в состояние, в котором он находился при входе в контекст. Это не позволяет тестам неожиданно менять фильтр предупреждений между запусками и приводить к неопределённым результатам. Функция showwarning() в модуле также восстанавливается до исходного значения. Примечание: это гарантируется только в однопоточном приложении. Если два или более потоков одновременно используют менеджер контекста catch_warnings, поведение не определено.
При тестировании нескольких операций, выдающих предупреждения одного типа, важно проводить тесты так, чтобы подтвердить, что каждая операция выдаёт новое предупреждение (например, настроить преобразование предупреждений в исключения и проверять, что операции вызывают исключения; проверять, что длина списка предупреждений увеличивается после каждой операции; либо удалять предыдущие записи из списка предупреждений перед каждой новой операцией).
Обновление кода для новых версий зависимостей
Категории предупреждений, представляющие интерес прежде всего для разработчиков Python (а не для конечных пользователей приложений на Python), по умолчанию игнорируются.
В частности, к этому списку «игнорируемых по умолчанию» предупреждений относится DeprecationWarning (для всех модулей, кроме __main__). Это означает, что разработчикам следует проверять свой код с включённым отображением предупреждений, которые обычно игнорируются, чтобы своевременно узнавать о будущих несовместимых изменениях API (как в стандартной библиотеке, так и в сторонних пакетах).
В идеальном случае у кода есть подходящий набор тестов, а средство запуска тестов автоматически включает все предупреждения при выполнении тестов (это делает средство запуска тестов из модуля unittest).
В менее идеальных случаях приложения можно проверить на использование устаревших интерфейсов, передав интерпретатору Python параметр -Wd (это сокращённая форма записи -W default) или задав в окружении PYTHONWARNINGS=default. Это включает обработку по умолчанию для всех предупреждений, в том числе тех, которые по умолчанию игнорируются. Чтобы изменить действие для обнаруженных предупреждений, можно изменить аргумент, передаваемый параметру -W (например, -W error). Дополнительные сведения о возможных вариантах см. в описании параметра -W.
Доступные функции
-
warnings.warn(message, category=None, stacklevel=1, source=None, *, skip_file_prefixes=()) -
Выдать предупреждение, проигнорировать его или вызвать исключение. Аргумент category, если он указан, должен быть классом категории предупреждения; по умолчанию используется
UserWarning. Вместо этого message может быть экземпляромWarning, и в этом случае аргумент category игнорируется, а используетсяmessage.__class__. В этом случае текст сообщения будетstr(message). Эта функция вызывает исключение, если выданное предупреждение преобразуется в ошибку с помощью фильтра предупреждений. Аргумент stacklevel можно использовать в написанных на Python функция-обёртках, например:def deprecated_api(message): warnings.warn(message, DeprecationWarning, stacklevel=2)Благодаря этому предупреждение будет указывать на вызывающий код
deprecated_api, а не на исходный код самогоdeprecated_api(иначе цель сообщения-предупреждения была бы утрачена).Ключевой аргумент skip_file_prefixes позволяет указать, какие кадры стека игнорировать при подсчёте уровней стека. Это может быть полезно, если нужно, чтобы предупреждение всегда указывало на места вызова за пределами пакета, когда постоянное значение stacklevel не подходит для всех путей вызова или его сложно поддерживать по другой причине. Если аргумент задан, он должен быть кортежем строк. При указании префиксов значение stacklevel неявно переопределяется на
max(2, stacklevel). Чтобы предупреждение указывало на вызывающий код за пределами текущего пакета, можно написать:# example/lower.py _warn_skips = (os.path.dirname(__file__),) def one_way(r_luxury_yacht=None, t_wobbler_mangrove=None): if r_luxury_yacht: warnings.warn("Please migrate to t_wobbler_mangrove=.", skip_file_prefixes=_warn_skips) # example/higher.py from . import lower def another_way(**kw): lower.one_way(**kw)Благодаря этому предупреждение будет указывать и на места вызова
example.lower.one_way(), и на места вызоваexample.higher.another_way(), только если вызывающий код находится за пределами пакетаexample.Если параметр source задан, это уничтоженный объект, выдавший
ResourceWarning.Изменено в версии 3.6: Добавлен параметр source.
Изменено в версии 3.12: Добавлен параметр skip_file_prefixes.
-
warnings.warn_explicit(message, category, filename, lineno, module=None, registry=None, module_globals=None, source=None) -
Это низкоуровневый интерфейс к функциональности
warn(), в который явно передаются сообщение, категория, имя файла и номер строки, а также, при необходимости, имя модуля и реестр (который должен быть словарём__warningregistry__модуля). По умолчанию имя модуля совпадает с именем файла без.py; если реестр не передан, предупреждение никогда не подавляется. message должен быть строкой, а category — подклассомWarning; также message может быть экземпляромWarning, и в этом случае аргумент category игнорируется.Если параметр module_globals задан, он должен представлять глобальное пространство имён, используемое кодом, для которого выдается предупреждение. (Этот аргумент позволяет отображать исходный код модулей, найденных в zip-файлах или других источниках импорта, не связанных с файловой системой.)
Если параметр source задан, это уничтоженный объект, выдавший
ResourceWarning.Изменено в версии 3.6: Добавлен параметр source.
-
warnings.showwarning(message, category, filename, lineno, file=None, line=None) -
Записать предупреждение в файл. Реализация по умолчанию вызывает
formatwarning(message, category, filename, lineno, line)и записывает полученную строку в file, по умолчанию —sys.stderr. Эту функцию можно заменить любой вызываемой функцией, присвоив еёwarnings.showwarning. line — это строка исходного кода, включаемая в сообщение-предупреждение; если line не задан,showwarning()попытается прочитать строку, указанную параметрами filename и lineno.
-
warnings.formatwarning(message, category, filename, lineno, line=None) -
Отформатировать предупреждение стандартным образом. Возвращает строку, которая может содержать символы новой строки и заканчивается символом новой строки. line — это строка исходного кода, включаемая в сообщение-предупреждение; если line не задан,
formatwarning()попытается прочитать строку, указанную параметрами filename и lineno.
-
warnings.filterwarnings(action, message='', category=Warning, module='', lineno=0, append=False) -
Добавить запись в список спецификаций фильтра предупреждений. По умолчанию запись добавляется в начало списка; если значение append равно true, запись добавляется в конец. Функция проверяет типы аргументов, компилирует регулярные выражения message и module и добавляет их в список фильтров предупреждений в виде кортежа. Если две записи соответствуют определённому предупреждению, запись, расположенная ближе к началу списка, имеет приоритет. Аргументы, которые не указаны, по умолчанию принимают значение, соответствующее любому варианту.
-
warnings.simplefilter(action, category=Warning, lineno=0, append=False) -
Добавить простую запись в список спецификаций фильтра предупреждений. Параметры функции имеют тот же смысл, что и в
filterwarnings(), но регулярные выражения не нужны: добавленный фильтр всегда соответствует любому сообщению в любом модуле, если совпадают категория и номер строки.
-
warnings.resetwarnings() -
Сбросить фильтр предупреждений. Это отменяет действие всех предыдущих вызовов
filterwarnings(), в том числе параметров командной строки-Wи вызововsimplefilter().
-
@warnings.deprecated(msg, *, category=DeprecationWarning, stacklevel=1) -
Декоратор, указывающий, что класс, функция или перегрузка устарели.
При применении этого декоратора к объекту во время выполнения могут выдаваться предупреждения об устаревании, когда объект используется. средства статической проверки типов также будут выдавать диагностическое сообщение при использовании устаревшего объекта.
Применение:
from warnings import deprecated from typing import overload @deprecated("Use B instead") class A: pass @deprecated("Use g instead") def f(): pass @overload @deprecated("int support is deprecated") def g(x: int) -> int: ... @overload def g(x: str) -> int: ...Предупреждение указанной категории category будет выдаваться во время выполнения при использовании устаревших объектов. Для функций это происходит при вызове, а для классов — при создании экземпляра и при создании подклассов. Если category равен
None, во время выполнения предупреждение не выдается. Параметр stacklevel определяет место выдачи предупреждения. Если он равен1(значение по умолчанию), предупреждение выдается непосредственно вызывающему коду устаревшего объекта; при большем значении оно выдается выше по стеку. Параметры category и stacklevel не влияют на поведение средств статической проверки типов.Переданное декоратору сообщение об устаревании сохраняется в атрибуте
__deprecated__декорированного объекта. При применении к перегрузке декоратор должен следовать за декоратором@~typing.overload, чтобы атрибут присутствовал у перегрузки, возвращаемой функциейtyping.get_overloads().Добавлено в версии 3.13: См. PEP 702.
Доступные менеджеры контекста
-
class warnings.catch_warnings(*, record=False, module=None, action=None, category=Warning, lineno=0, append=False) -
Менеджер контекста, который сохраняет фильтр предупреждений и функцию
showwarning(), а при выходе восстанавливает их. Если аргумент record равенFalse(значение по умолчанию), при входе менеджер контекста возвращаетNone. Если record равенTrue, возвращается список, который постепенно пополняется объектами, перехваченными пользовательской функциейshowwarning()(она также подавляет вывод вsys.stdout). У каждого объекта в списке есть атрибуты с теми же именами, что и аргументыshowwarning().Аргумент module принимает модуль, который будет использоваться вместо модуля, возвращаемого при импорте
warnings; его фильтр будет защищён. Этот аргумент предназначен главным образом для тестирования самого модуляwarnings.Если аргумент action не равен
None, остальные аргументы передаются вsimplefilter(), как если бы она была вызвана сразу при входе в контекст.Значение параметров category и lineno см. в разделе Фильтр предупреждений.
Примечание
Менеджер
catch_warningsработает так: он заменяет функциюshowwarning()модуля и внутренний список спецификаций фильтров, а затем восстанавливает их. Это означает, что менеджер контекста изменяет глобальное состояние и поэтому не является потокобезопасным.Изменено в версии 3.11: Добавлены параметры action, category, lineno и append.
© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/warnings.html