Поднять предупреждение в Python без прерывания программы

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

Я использую следующую простую функцию, которая только проверяет, передал ли пользователь ей ненулевое число. Если пользователь передает ноль, программа должна предупредить пользователя, но продолжить в обычном режиме. Он должен работать как следующий код, но должен использовать класс Warning(), Error() или Exception() вместо вывода предупреждения вручную.

def is_zero(i):
   if i != 0:
     print "OK"
   else:
     print "WARNING: the input is 0!"
   return i

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

def is_zero(i):
   if i != 0:
     print "OK"
   else:
     raise Warning("the input is 0!")
   return i

Я хочу быть в состоянии проверить, что было выдано предупреждение, проверяя его на unittest. Если я просто распечатываю сообщение, я не могу проверить его с помощью assertRaises в unittest.

Ответ 1

Вы не должны raise предупреждать, вы должны использовать warnings. Поднимая его, вы генерируете ошибку, а не предупреждение.

Ответ 2

import warnings
warnings.warn("Warning...........Message")

См. документацию по python: здесь

Ответ 3

По умолчанию, в отличие от исключения, предупреждение не прерывается.

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

>>> warnings.warn('This is my lazy warning.')
<string>:1: UserWarning: This is my lazy warning.

Чтобы просто использовать ранее существующий класс, например, Warning:

>>> warnings.warn('This is my generic warning.', Warning)
<string>:1: Warning: This is my generic warning.

Создание настраиваемого класса предупреждений аналогично созданию настраиваемого класса исключений:

>>> class MyCustomWarning(UserWarning):
...     pass
... 
... warnings.warn('This is my custom warning.', MyCustomWarning)

<string>:1: MyCustomWarning: This is my custom warning.

Для тестирования рассмотрите assertWarns или assertWarnsRegex.


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