Піднімайте попередження в 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. Якщо я просто надрукував повідомлення, я не зможу перевірити його за допомогою assrtRaises в unittest.


Як саме Ви хочете повідомити користувача? через електронну пошту чи SMS? причина, яка може бути підключена, але ви повинні бути конкретними.
aaronasterling

2
Чому ви не просто printповідомлення?
sje397

1
@ sje397 Справа в тому, що я хочу мати можливість перевірити, що попередження було кинуто, перевіряючи його по unittest. Якщо я просто роздрукую повідомлення, я не можу це зробити з assertRaises в unittest.
Томаш Новотний

Відповіді:


157

Ви не повинні raiseпопереджати, ви повинні використовувати warningsмодуль. Підвищуючи це, ви генеруєте помилку, а не попередження.


1
Велике спасибі. І як тоді я перевіряю, що Попередження було кинуто за допомогою unittest? Я більше не можу використовувати assertRaises ().
Томаш Новотний

@Tomas Novotny ви можете зафіксувати stdout та stderr, а потім перевірте, чи є рядки, видані вашим попередженням, всередині.
пшениці

15
@Tomas: Я ніколи не чув про бажання перевірити на попередження, але є доступний warnings.catch_warningsконтекстний менеджер, який дозволить вам це зробити.
SilentGhost

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

Дивіться документацію пітона: тут


6
А warnings.warn("blabla", DeprecationWarning)для додавання класу у вигляді попередження видаються
Шаді

52

За замовчуванням, на відміну від винятку, попередження не переривається.

Після import 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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.