strivn
strivn

Reputation: 339

Catch two types of warning

So I want to catch different types of warnings on the following code:

score = cross_val_score(DecisionTreeClassifier(), X, y, scoring=f2_measure, cv=cv)

From running the code, I got two warnings:

UserWarning: The least populated class in y has only 1 members, which is less than n_splits=2.
  % (min_groups, self.n_splits)), UserWarning)

UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 due to no true nor predicted samples. 
  Use `zero_division` parameter to control this behavior.

I'd like to catch both type of warnings and then handle them separately, I tried using the following:

with warnings.catch_warnings():
    warnings.filterwarnings('error', category=UserWarning)
    warnings.filterwarnings('error', category=UndefinedMetricWarning)
    try:
        score = cross_val_score(DecisionTreeClassifier(), X, y, scoring=f2_measure, cv=cv).mean()
    except (UndefinedMetricWarning, UserWarning) as e:
        print(type(e))

But all of the warnings are then raised as a UserWarning, and there's no UndefinedMetricWarning. (I'm not quite sure but I think this problem might be caused by UndefinedMetricWarning is inherited from UserWarning).

How to identify and handle these two type of warnings separately?

Upvotes: 3

Views: 642

Answers (1)

Ryan Ly
Ryan Ly

Reputation: 51

You can use two different excepts after your try. The second except will catch only the exceptions that are not caught by the first except. So you can make the first except catch the subclass UndefinedMetricWarning and then the second except can effectively catch only the UserWarning warnings that are not also an UndefinedMetricWarning:

with warnings.catch_warnings():
    warnings.filterwarnings('error', category=UserWarning)
    warnings.filterwarnings('error', category=UndefinedMetricWarning)
    try:
        score = cross_val_score(DecisionTreeClassifier(), X, y, scoring=f2_measure, cv=cv).mean()
    except UndefinedMetricWarning as e:
        print(type(e))
    except UserWarning as e:
        print(type(e))

Here is a minimal working example:

import warnings

class MyWarning(UserWarning):
    pass

def a(flag):
    if flag:
        warnings.warn("hello", MyWarning)
    else:
        warnings.warn("bye")

def b(flag):
    with warnings.catch_warnings():
        warnings.filterwarnings("error", category=UserWarning)
        warnings.filterwarnings("error", category=MyWarning)
        try:
            a(flag)
        except MyWarning as e:
            print(type(e))
        except UserWarning as e:
            print(type(e))

b(True)
b(False)

See: https://docs.python.org/3/tutorial/errors.html

Upvotes: 2

Related Questions