Піднімайте попередження в 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.