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

189

Я пытаюсь поднять предупреждение в 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.

Томас Новотный
источник
Как именно вы хотите уведомить пользователя? через электронную почту или смс? причина, которая может быть подключена, но вы должны быть конкретными.
aaronasterling
2
Почему ты не просто printсообщение?
sje397
1
@ sje397 Суть в том, что я хочу иметь возможность проверить, что было выдано предупреждение, проверяя его на unittest. Если я просто распечатываю сообщение, я не могу сделать это с помощью assertRaises в unittest.
Томас Новотный

Ответы:

157

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

SilentGhost
источник
1
Большое спасибо. И как тогда я могу проверить, что предупреждение было выдано с помощью unittest? Я не могу использовать assertRaises () больше.
Томас Новотный
@Tomas Novotny вы можете захватить stdout и stderr, а затем проверить, что строки, выданные вашим предупреждением, находятся внутри.
пшеница
15
@ Томас: Я никогда не слышал о желании проверить на предупреждение, но есть warnings.catch_warningsменеджер контекста, который позволит вам сделать это.
SilentGhost
290
import warnings
warnings.warn("Warning...........Message")

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

некромант
источник
6
И warnings.warn("blabla", DeprecationWarning)для добавления класса к виду выдаваемого предупреждения
Шади
52

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

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

>>> warnings.warn('This is a default warning.')
<string>:1: UserWarning: This is a default warning.

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

>>> warnings.warn('This is a particular warning.', DeprecationWarning)
<string>:1: DeprecationWarning: This is a particular warning.

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

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

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

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


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

Акаменус
источник