Рубрики
Без рубрики

Предупреждения – нефатальные оповещения

Автор оригинала: Doug Hellmann.

Цель:

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

MODULE MODULE был представлен pep 230 Как способ предупредить программистов об изменениях в языках или объектах библиотеки в ожидании обратного несовместимых изменений, приходящих с Python 3.0. Он также может быть использован для сообщения о возмещенных ошибках конфигурации или деградации функций от недостающих библиотек. Лучше доставить пользовательские сообщения через модуль для ведения журнала, потому что предупреждения, отправленные на консоль, могут быть потеряны.

Поскольку предупреждения не являются смертельными, программа может много раз столкнуться с той же предупреждением. Модуль <Код> Модуль подавляет повторные сообщения от одного и того же источника, чтобы сократить раздражение о том же предупреждении и снова. Выход можно управлять в каждом конкретном случае, используя параметры командной строки к интерпретатору, либо путем вызова функций, найденных в Предупреждения .

Категории и фильтрация

Предупреждения классифицируются с использованием подклассов встроенного класса исключения <Код> Предупреждение . Несколько стандартных значений описаны в онлайн-документации для модуля Code> , а пользовательские предупреждения могут быть добавлены по подклассам из <Код> Предупреждение .

Предупреждения обрабатываются на основе настроек . Фильтр состоит из пяти частей: ACTIME , Сообщение , <Код> Категория , <Код> Модуль , а также номер <код> . Сообщение Portion фильтра – это регулярное выражение, которое используется для соответствия тексту предупреждения. категория – это имя класса исключения. Модуль содержит регулярное выражение, которое должно соответствовать имени модуля, генерирующего предупреждение. И номер линии может использоваться для изменения обработки на определенные вхождения предупреждения.

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

ПРЕДУПРЕЖДЕНИЕ Действия фильтра

Действие

Смысл

ошибка

Поверните предупреждение в исключение.

игнорировать

Откажитесь от предупреждения.

всегда

Всегда выделяйте предупреждение.

дефолт

Распечатайте предупреждение в первый раз, когда он генерируется из каждого местоположения.

модуль

Распечатайте предупреждение в первый раз, когда он генерируется из каждого модуля.

однажды

Распечатайте предупреждение в первый раз, когда он генерируется.

Создание предупреждений

Самый простой способ издать предупреждение – звонить <код> Warn () с сообщением в качестве аргумента.

warnings_warn.py

import warnings

print('Before the warning')
warnings.warn('This is a warning message')
print('After the warning')

Затем, когда программа запускается, сообщение печатается.

$ python3 -u warnings_warn.py

Before the warning
warnings_warn.py:13: UserWarning: This is a warning message
  warnings.warn('This is a warning message')
After the warning

Несмотря на то, что предупреждение напечатано, поведение по умолчанию – продолжить прошедшее значение и запустить остальную часть программы. Это поведение можно изменить с помощью фильтра.

warnings_warn_raise.py

import warnings

warnings.simplefilter('error', UserWarning)

print('Before the warning')
warnings.warn('This is a warning message')
print('After the warning')

В этом примере функция SICEFILTER () добавляет запись в список внутренних фильтров, чтобы сообщить модулю , чтобы поднять исключение, когда <код> Userwarning Предупреждение выдается.

$ python3 -u warnings_warn_raise.py

Before the warning
Traceback (most recent call last):
  File "warnings_warn_raise.py", line 15, in 
    warnings.warn('This is a warning message')
UserWarning: This is a warning message

Поведение фильтра также можно контролировать из командной строки, используя опцию -w для интерпретатора. Укажите свойства фильтра в виде строки с пятью частями (действие, сообщение, категорию, модулем и числом строки), разделенные двоеточиями (: ). Например, если Warnings_warn.py запущен с помощью фильтра, установленного для повышения ошибки на UserWarning , производится исключением.

$ python3 -u -W "error::UserWarning::0" warnings_warn.py

Before the warning
Traceback (most recent call last):
  File "warnings_warn.py", line 13, in 
    warnings.warn('This is a warning message')
UserWarning: This is a warning message

Поскольку поля для Message и Module Module остались пустыми, они были интерпретированы как что-либо подходящее.

Фильтрация с шаблонами

Чтобы отфильтровать более сложные правила программно, используйте FILTERWARNINGS () . Например, чтобы фильтровать на основе содержимого текста сообщения, дайте регулярную структуру выражения в качестве сообщения Agent .

warnings_filterwarnings_message.py

import warnings

warnings.filterwarnings('ignore', '.*do not.*',)

warnings.warn('Show this message')
warnings.warn('Do not show this message')

Шаблон содержит «<код> не », но фактическое сообщение использует «<код> не ». Шаблон соответствует, потому что регулярное выражение всегда скомпилировано, чтобы искать нечувствительные случаи совпадения.

$ python3 warnings_filterwarnings_message.py

warnings_filterwarnings_message.py:14: UserWarning: Show this
message
  warnings.warn('Show this message')

Пример программы ниже генерирует два предупреждения.

warnings_filter.py

import warnings

warnings.warn('Show this message')
warnings.warn('Do not show this message')

Одним из предупреждений можно игнорировать с помощью аргумента фильтра в командной строке.

$ python3 -W "ignore:do not:UserWarning::0" warnings_filter.py

warnings_filter.py:12: UserWarning: Show this message
  warnings.warn('Show this message')

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

warnings_filterwarnings_module.py

import warnings

warnings.filterwarnings(
    'ignore',
    '.*',
    UserWarning,
    'warnings_filter',
)

import warnings_filter

Поскольку фильтр на месте, предупреждаются предупреждения, когда Warnings_Filter импортируется.

$ python3 warnings_filterwarnings_module.py

Чтобы подавить только сообщение по линии 13 Warnings_Filter , включите номер строки в качестве последнего аргумента Filterwarnings () . Используйте фактический номер строки из исходного файла, чтобы ограничить фильтр или <код> 0 , чтобы фильтр применил к всем вхождению сообщения.

warnings_filterwarnings_lineno.py

import warnings

warnings.filterwarnings(
    'ignore',
    '.*',
    UserWarning,
    'warnings_filter',
    13,
)

import warnings_filter

Шаблон соответствует любому сообщению, поэтому важные аргументы – это имя модуля и номер строки.

$ python3 warnings_filterwarnings_lineno.py

.../warnings_filter.py:12: UserWarning: Show this message
  warnings.warn('Show this message')

Повторные предупреждения

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

warnings_repeated.py

import warnings


def function_with_warning():
    warnings.warn('This is a warning!')


function_with_warning()
function_with_warning()
function_with_warning()

Этот пример несколько раз вызывает одну и ту же функцию, но дает одно предупреждение.

$ python3 warnings_repeated.py

warnings_repeated.py:14: UserWarning: This is a warning!
  warnings.warn('This is a warning!')

<Код> «один раз» действие может использоваться для подавления случаев того же сообщения из разных мест.

warnings_once.py

import warnings

warnings.simplefilter('once', UserWarning)

warnings.warn('This is a warning!')
warnings.warn('This is a warning!')
warnings.warn('This is a warning!')

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

$ python3 warnings_once.py

warnings_once.py:14: UserWarning: This is a warning!
  warnings.warn('This is a warning!')

Точно так же <код> «модуль» подавляет повторные сообщения из того же модуля, независимо от номера строки.

Альтернативные функции доставки сообщений

Обычно предупреждения напечатаны в SYS.STDERR . Измените это поведение, заменив функцию Showwarning () внутри Предупреждения Module. Например, чтобы отправить предупреждения в файл журнала вместо стандартной ошибки, замените <код> Showwarning () с функцией, которая регистрирует предупреждение.

warnings_showwarning.py

import warnings
import logging


def send_warnings_to_log(message, category, filename, lineno,
                         fileNone, lineNone):
    logging.warning(
        '%s:%s: %s:%s',
        filename, lineno,
        category.__name__, message,
    )


logging.basicConfig(levellogging.INFO)

old_showwarning  warnings.showwarning
warnings.showwarning  send_warnings_to_log

warnings.warn('message')

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

$ python3 warnings_showwarning.py

WARNING:root:warnings_showwarning.py:28: UserWarning:message

Форматирование

Если предупреждения должны перейти к стандартной ошибке, но они должны быть переформатированы, заменить <код> FormatWarning () .

warnings_formatwarning.py

import warnings


def warning_on_one_line(message, category, filename, lineno,
                        fileNone, lineNone):
    return '-> {}:{}: {}:{}'.format(
        filename, lineno, category.__name__, message)


warnings.warn('Warning message, before')
warnings.formatwarning  warning_on_one_line
warnings.warn('Warning message, after')

Функция формата должна вернуть одну строку, содержащую представление предупреждения, которое будет отображаться пользователю.

$ python3 -u warnings_formatwarning.py

warnings_formatwarning.py:19: UserWarning: Warning message,
before
  warnings.warn('Warning message, before')
-> warnings_formatwarning.py:21: UserWarning:Warning message,
after

Уровень стека в предупреждениях

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

warnings_warn_stacklevel.py

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
# encoding: utf-8

import warnings


def old_function():
    warnings.warn(
        'old_function() is deprecated, use new_function()',
        stacklevel2)


def caller_of_old_function():
    old_function()


caller_of_old_function()

В этом примере <код> предупреждают () необходимо подняться на стек два уровня, один для себя и один для <код> OLD_Function () .

$ python3 warnings_warn_stacklevel.py

warnings_warn_stacklevel.py:14: UserWarning: old_function() is deprecated,
 use new_function()
  old_function()

Смотрите также