mjsxbo
mjsxbo

Reputation: 2266

How to print only first occurrence of python warning?

I have a function which is called at many different times. The function must print a warning, but only the first time. The warning should not be printed every time the function is called.

def func():
    if(condition):
        warnings.warn('warn message',RuntimeWarning)

How do I ensure that this warning is only printed the first time condition is true and not every subsequent time.

None of the other answers helped me. I came across warning filters, but I don't understand how to use that here.

Upvotes: 0

Views: 1844

Answers (2)

srjjio
srjjio

Reputation: 1049

Solution could probably be found around there: https://docs.python.org/2/library/warnings.html#warning-filter

warnings.simplefilter('once', RuntimeWarning)

Here custom solutions using decorators: you don't have to change your function implementation to a class, you keep the logic to catch the first warning separated from the rest of your code.

For warn:

def warn_only_once(function):
    function.already_warned = False
    def wrapper(*args, **kwargs):
        with warnings.catch_warnings(record=function.already_warned):
            function.already_warned = not function.already_warned
            return function(*args, **kwargs)
    return wrapper

@warn_only_once
def test():
     warning.warn('hello', RuntimeWarning)

For raise:

def warn_only_once(function):
    function.already_warned = False
    def wrapper(*args, **kwargs):
        try:
            return function(*args, **kwargs)
        except RuntimeWarning as warning:
            if not function.already_warned:
               function.already_warned = True
               raise warning
    return wrapper

@warn_only_once
def test():
     raise RuntimeWarning('hello')

Upvotes: 4

francisco sollima
francisco sollima

Reputation: 8338

You can use an auxiliary variable that starts being false and turns to true on the first warning. If you must execute the function multiple times, an easy solution would be to wrap it inside a class, and store the variable in the instance of the class:

class MyClass(object):
    def __init__(self):
        self.first_warning = False
    def func(self):
        if(condition) and not self.first_warning:
            warnings.warn('warn message',RuntimeWarning)
            self.first_warning = True

m = MyClass()
m.func()  # only the first time the condition is met, the warning will occur
m.func()
m.func()

Upvotes: 1

Related Questions