Warning

Les warning ne sont pas des erreurs mais des soupçons d’erreurs. Le programme peut continuer mais il est possible qu’il s’arrête un peu plus tard et la cause pourrait être un warning déclenché un peu plus tôt.

Un des warning les plus utilisé est le DeprecationWarning qui indique que le code utilisé va disparaître sous cette forme lors des prochaines release. scikit-learn suit la règle suivante à chaque fois qu’une API change, un warning subsiste pendant deux release pour une fonction appelée à disparaître. Le warning apparaît à chaque fois qu’elle est exécutée, puis la fonction est finalement supprimée. Tout code s’appuyant encore sur cette fonction provoquera une erreur.

Générer un warning

Le module warnings permet de lancer un warning comme ceci :

<<<

import warnings
warnings.warn("Warning lancé !")

>>>

    :4: UserWarning: Warning lancé !

Il est préférable d’ailleurs de spécifier un type précis de warning qui indique à l’utilisateur à quel type d’erreur il s’expose sans avoir à lire le message, voire plus tard de les trier.

<<<

import warnings
warnings.warn("Warning d'un certain lancé !", UserWarning)

>>>

    :4: UserWarning: Warning d'un certain lancé !

Intercepter un warning

Les warning sont parfois très agaçants car il s’insère dans les sorties du programme qui deviennent moins lisibles. Il serait préférable de les corriger mais ils surviennent parfois dans un module qui n’a pas pris en compte l’évolution d’une de ses dépendances. Il est difficile de corriger cette erreur immédiatement à moins de modifier le code du module installé, ce qui n’est souvent pas souhaitable voire impossible si ce module est écrit en C++. Le plus simple reste de les intercepter.

<<<

import warnings


def fxn():
    warnings.warn("deprecated", DeprecationWarning)


with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()

>>>

    

On peut également intercepter un type particulier de warning, c’est le rôle de la classe catch_warnings :

<<<

import warnings


def fxn():
    warnings.warn("deprecated", DeprecationWarning)


print("Boucle 1")
with warnings.catch_warnings():
    warnings.simplefilter("ignore", DeprecationWarning)
    fxn()

print("Boucle 2")
with warnings.catch_warnings():
    warnings.simplefilter("ignore", UserWarning)
    fxn()

print("Boucle 3")
with warnings.catch_warnings():
    warnings.simplefilter("ignore", DeprecationWarning)
    warnings.simplefilter("ignore", UserWarning)
    fxn()

>>>

    Boucle 1
    Boucle 2
    :6: DeprecationWarning: deprecated
    Boucle 3

Il est parfois utile de mémoriser les warning généré par un programme, c’est nécessaire principalement lorsqu’on écrit des tests unitaires.

<<<

import warnings


def fxn():
    warnings.warn("deprecated", DeprecationWarning)


with warnings.catch_warnings(record=True) as ws:
    warnings.simplefilter("always")
    fxn()

    print("nombre de warnings :", len(ws))

    for i, w in enumerate(ws):
        print("warning {0} : {1}".format(i, w))

>>>

    nombre de warnings : 1
    warning 0 : {message : DeprecationWarning('deprecated'), category : 'DeprecationWarning', filename : '', lineno : 6, line : None}

Warning personnalisé

Comme pour les exceptions, il est possible de définir ses propres warning en héritant d’un warning en particulier.

<<<

import warnings


class MonWarning(UserWarning):
    pass


warnings.warn("mon warning", MonWarning)

>>>

    :8: MonWarning: mon warning