warnings
--- Contrôle des alertes¶
Code source: Lib/warnings.py
Les messages d'avertissement sont généralement émis dans les situations où il est utile d'alerter l'utilisateur d'un problème dans un programme, mais qu'il n'est pas justifié de lever une exception et de le terminer. Par exemple, on peut vouloir émettre un avertissement lorsqu'un programme utilise un module obsolète.
Les développeurs Python émettent des avertissements en appelant la fonction warn()
définie dans ce module. (Les développeurs C utilisent PyErr_WarnEx()
; voir Gestion des exceptions pour plus d'informations).
Les messages d'avertissement sont normalement écrits sur sys.stderr
, mais leurs effets peuvent être modifiés, il est possible d'ignorer tous les avertissements ou au contraire les transformer en exceptions. L'effet des avertissements peut varier selon la catégorie d'avertissement, de son texte et d'où il est émis. Les répétitions du même avertissement depuis une même source sont généralement ignorées.
La gestion des avertissements se fait en deux étapes : premièrement, chaque fois qu'un avertissement est émis, le module détermine si un message doit être émis ou non ; ensuite, si un message doit être émis, il est formaté et affiché en utilisant une fonction qui peut être définie par l'utilisateur.
Un filtre (une séquence de règles) est utilisé pour décider si un message d'avertissement doit être émis ou non. Des règles peuvent être ajoutées au filtre en appelant filterwarnings()
et remises à leur état par défaut en appelant resetwarnings()
.
L'affichage des messages d'avertissement se fait en appelant la fonction showwarning()
, qui peut être redéfinie ; l'implémentation par défaut formate le message en appelant formatwarning()
, qui peut également être réutilisée par une implémentation personnalisée.
Voir aussi
logging.captureWarnings()
vous permet de gérer tous les avertissements avec l'infrastructure de journalisation standard.
Catégories d'avertissement¶
Il existe un certain nombre d'exceptions natives qui représentent des catégories d'avertissement. Cette catégorisation est utile pour filtrer les groupes d'avertissements.
Bien qu'il s'agisse techniquement d'exceptions, les exceptions natives sont documentées ici, parce qu'elles appartiennent conceptuellement au mécanisme des avertissements.
Le code utilisateur peut définir des catégories d'avertissement supplémentaires en héritant l'une des catégories d'avertissement standard. Une catégorie d'avertissement doit toujours hériter de la classe Warning
.
Les classes de catégories d'avertissement suivantes sont actuellement définies :
Classe |
Description |
---|---|
Il s'agit de la classe de base de toutes les classes de catégories d'avertissement. C'est une sous-classe de |
|
Catégorie par défaut pour |
|
Catégorie de base pour les avertissements sur les fonctionnalités obsolètes lorsque ces avertissements sont destinés à d'autres développeurs Python (ignorées par défaut, sauf si elles proviennent de |
|
Catégorie de base pour les avertissements concernant les syntaxes douteuses. |
|
Catégorie de base pour les avertissements concernant les fonctionnalités douteuses à l'exécution. |
|
Catégorie de base pour les avertissements concernant les fonctionnalités obsolètes lorsque ces avertissements sont destinés aux utilisateurs finaux des programmes écrits en Python. |
|
Catégorie de base pour les avertissements concernant les fonctionnalités qui seront obsolètes dans le futur (ignorée par défaut). |
|
Catégorie de base pour les avertissements déclenchés lors de l'importation d'un module (ignoré par défaut). |
|
Catégorie de base pour les avertissements relatifs à Unicode. |
|
Catégorie de base pour les avertissements relatifs à |
|
Catégorie de base pour les avertissements relatifs à l'utilisation des ressources. |
Modifié dans la version 3.7: Avant, la différence entre DeprecationWarning
et FutureWarning
était que l'un était dédié aux fonctionnalités retirées, et l'autre aux fonctionnalités modifiées. La différence aujourd'hui est plutôt leur audience et la façon dont ils sont traités par les filtres d'avertissement par défaut.
Le filtre des avertissements¶
Le filtre des avertissements contrôle si les avertissements sont ignorés, affichés ou transformés en erreurs (ce qui lève une exception).
Conceptuellement, le filtre d'avertissements maintient une liste ordonnée d'entrées ; chaque avertissement est comparé à chaque entrée de la liste jusqu'à ce qu'une correspondance soit trouvée ; l'entrée détermine l'action à effectuer. Chaque entrée est un quintuplet de la forme (action, message, catégorie, module, lineno), où :
action est l'une des chaînes de caractères suivantes :
Valeur
Action
"default"
affiche la première occurrence des avertissements correspondants pour chaque emplacement (module + numéro de ligne) où l'avertissement est émis
"error"
transforme les avertissements correspondants en exceptions
"ignore"
ignore les avertissements correspondants
"always"
affiche toujours les avertissements correspondants
"module"
affiche la première occurrence des avertissements correspondants pour chaque module où l'avertissement est émis (quel que soit le numéro de ligne)
"once"
n'affiche que la première occurrence des avertissements correspondants, quel que soit l'endroit où ils se trouvent
message est une chaîne de caractères contenant une expression régulière avec laquelle le début du message d'avertissement doit correspondre. L'expression est compilée pour être toujours insensible à la casse.
category est une classe (une sous-classe de
Warning
) dont la catégorie d'avertissement doit être une sous-classe afin de correspondre.module est une chaîne de caractères contenant une expression régulière avec laquelle le nom du module doit correspondre. L'expression est compilée pour être sensible à la casse.
lineno est le numéro de ligne d'où l'avertissement doit provenir, ou
0
pour correspondre à tous les numéros de ligne.
Puisque que la classe Warning
hérite de la classe Exception
, pour transformer un avertissement en erreur, il suffit de lever category(message)
.
Si un avertissement est signalé et ne correspond à aucun filtre enregistré, l'action default
est appliquée (d'où son nom).
Rédaction de filtres d'avertissement¶
Le filtre des avertissements est initialisé par les options -W
passées à la ligne de commande de l'interpréteur Python et la variable d'environnement PYTHONWARNINGS
. L'interpréteur enregistre les arguments de toutes les entrées fournies sans interprétation dans sys.warnoptions
; le module warnings
les analyse lors de la première importation (les options invalides sont ignorées, et un message d'erreur est envoyé à sys.stderr
).
Les filtres d'avertissement individuels sont décrits sous la forme d'une séquence de champs séparés par des deux-points :
action:message:category:module:line
La signification de chacun de ces champs est décrite dans Le filtre des avertissements. Plusieurs filtres peuvent être écrits en une seule ligne (comme pour PYTHONWARNINGS
), ils sont dans ce cas séparés par des virgules, et les filtres listés plus en dernier ont priorité sur ceux qui les précèdent (car ils sont appliqués de gauche à droite, et les filtres les plus récemment appliqués ont priorité sur les précédents).
Les filtres d'avertissement couramment utilisés s'appliquent à tous les avertissements, aux avertissements d'une catégorie particulière ou aux avertissements émis par certains modules ou paquets. Quelques exemples :
default # Show all warnings (even those ignored by default)
ignore # Ignore all warnings
error # Convert all warnings to errors
error::ResourceWarning # Treat ResourceWarning messages as errors
default::DeprecationWarning # Show DeprecationWarning messages
ignore,default:::mymodule # Only report warnings triggered by "mymodule"
error:::mymodule[.*] # Convert warnings to errors in "mymodule"
# and any subpackages of "mymodule"
Filtre d'avertissement par défaut¶
Par défaut, Python installe plusieurs filtres d'avertissement, qui peuvent être outrepassés par l'option -W
en ligne de commande, la variable d'environnement PYTHONWARNINGS
et les appels à filterwarnings()
.
Dans les versions standard publiées de Python, le filtre d'avertissement par défaut a les entrées suivantes (par ordre de priorité) :
default::DeprecationWarning:__main__
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::ResourceWarning
Dans les versions de débogage, la liste des filtres d'avertissement par défaut est vide.
Modifié dans la version 3.2: DeprecationWarning
est maintenant ignoré par défaut en plus de PendingDeprecationWarning
.
Modifié dans la version 3.7: DeprecationWarning
est à nouveau affiché par défaut lorsqu'il provient directement de __main__
.
Modifié dans la version 3.7: BytesWarning
n'apparaît plus dans la liste de filtres par défaut et est configuré via sys.warnoptions
lorsque l'option -b
est donnée deux fois.
Outrepasser le filtre par défaut¶
Les développeurs d'applications écrites en Python peuvent souhaiter cacher tous les avertissements Python à leurs utilisateurs, et ne les afficher que lorsqu'ils exécutent des tests ou travaillent sur l'application. L'attribut sys.warnoptions
utilisé pour passer les configurations de filtre à l'interpréteur peut être utilisé comme marqueur pour indiquer si les avertissements doivent être ou non désactivés :
import sys
if not sys.warnoptions:
import warnings
warnings.simplefilter("ignore")
Les développeurs d'exécuteurs de test pour le code Python sont invités à s'assurer que tous les avertissements sont affichés par défaut pour le code en cours de test, en utilisant par exemple :
import sys
if not sys.warnoptions:
import os, warnings
warnings.simplefilter("default") # Change the filter in this process
os.environ["PYTHONWARNINGS"] = "default" # Also affect subprocesses
Enfin, les développeurs d'interpréteurs de commandes interactifs qui exécutent du code utilisateur dans un espace de nommage autre que __main__
sont invités à s'assurer que les messages DeprecationWarning
sont rendus visibles par défaut, en utilisant le code suivant (où user_ns
est le module utilisé pour exécuter le code entré interactivement) :
import warnings
warnings.filterwarnings("default", category=DeprecationWarning,
module=user_ns.get("__name__"))
Suppression temporaire des avertissements¶
Si vous utilisez un code dont vous savez qu'il va déclencher un avertissement, comme une fonction obsolète, mais que vous ne voulez pas voir l'avertissement (même si les avertissements ont été explicitement configurés via la ligne de commande), alors il est possible de supprimer l'avertissement en utilisant le gestionnaire de contexte catch_warnings
:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
Dans le gestionnaire de contexte, tous les avertissements sont simplement ignorés. Ceci vous permet d'utiliser du code déclaré obsolète sans voir l'avertissement tout en ne supprimant pas l'avertissement pour un autre code qui pourrait ne pas être conscient de son utilisation de code déprécié. Remarque : ceci ne peut être garanti que dans une application utilisant un seul fil d'exécution. Si deux ou plusieurs threads utilisent le gestionnaire de contexte catch_warnings
en même temps, le comportement est indéfini.
Tester les avertissements¶
Pour tester les avertissements générés par le code, utilisez le gestionnaire de contexte catch_warnings
. Avec lui, vous pouvez temporairement modifier le filtre d'avertissements pour faciliter votre test. Par exemple, procédez comme suit pour capturer tous les avertissements levés à vérifier :
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
Vous pouvez aussi faire en sorte que tous les avertissements soient des exceptions en utilisant error
au lieu de always
. Il faut savoir que si un avertissement a déjà été émis à cause d'une règle once
ou default
, quel que soit le filtre activé, l'avertissement ne sera pas revu à moins que le registre des avertissements lié à l'avertissement ait été vidé.
A sa sortie, le gestionnaire de contexte restaure le filtre des avertissements dans l'état où il était au démarrage du contexte. Cela empêche les tests de changer le filtre d'avertissements de manière inattendue entre les tests et d'aboutir à des résultats de test indéterminés. La fonction showwarning()
du module est également restaurée à sa valeur originale. Remarque : ceci ne peut être garanti que dans une application mono-threadées. Si deux ou plusieurs fils d'exécution utilisent le gestionnaire de contexte catch_warnings
en même temps, le comportement est indéfini.
Lorsque vous testez plusieurs opérations qui provoquent le même type d'avertissement, il est important de les tester d'une manière qui confirme que chaque opération provoque un nouvel avertissement (par exemple, définissez les avertissements comme exceptions et vérifiez que les opérations provoquent des exceptions, vérifiez que la longueur de la liste des avertissements continue à augmenter après chaque opération, ou bien supprimez les entrées précédentes de la liste des avertissements avant chaque nouvelle opération).
Mise à jour du code pour les nouvelles versions des dépendances¶
Les catégories d'avertissement qui intéressent principalement les développeurs Python (plutôt que les utilisateurs finaux d'applications écrites en Python) sont ignorées par défaut.
Notamment, cette liste "ignorés par défaut" inclut DeprecationWarning
(pour chaque module sauf __main__
), ce qui signifie que les développeurs doivent s'assurer de tester leur code avec des avertissements généralement ignorés rendus visibles afin de recevoir des notifications rapides des changements d'API (que ce soit dans la bibliothèque standard ou les paquets tiers).
Dans le cas idéal, le code dispose d'une suite de tests appropriée, et le testeur se charge d'activer implicitement tous les avertissements lors de l'exécution des tests (le testeur fourni par le module unittest
le fait).
Dans des cas moins idéaux, l'utilisation de d'interfaces obsolète peut être testé en passant -Wd
à l'interpréteur Python (c'est une abréviation pour -W default
) ou en définissant PYTHONWARNINGS=default
dans l'environnement. Ceci permet la gestion par défaut de tous les avertissements, y compris ceux qui sont ignorés par défaut. Pour changer l'action prise pour les avertissements rencontrés, vous pouvez changer quel argument est passé à -W
(par exemple -W error
). Voir l'option -W
pour plus de détails sur ce qui est possible.
Fonctions disponibles¶
-
warnings.
warn
(message, category=None, stacklevel=1, source=None)¶ Émet, ignore, ou transforme en exception un avertissement. L'argument category, s'il est donné, doit être une classe de warning category class ; et vaut par défaut
UserWarning
. Aussi message peut être une instance deWarning
, auquel cas category sera ignoré etmessage.__class__
sera utilisé. Dans ce cas, le texte du message serastr(message)
. Cette fonction lève une exception si cet avertissement particulier émis est transformé en erreur par le filtre des avertissements. L'argument stacklevel peut être utilisé par les fonctions wrapper écrites en Python, comme ceci :def deprecation(message): warnings.warn(message, DeprecationWarning, stacklevel=2)
Fait en sorte que l'avertissement se réfère à l'appelant de
deprecation()
plutôt qu'à la source dedeprecation()
elle-même (puisque celle-ci irait à l'encontre du but du message d'avertissement).source, s'il est fourni, est l'objet détruit qui a émis un
ResourceWarning
.Modifié dans la version 3.6: Ajout du paramètre source.
-
warnings.
warn_explicit
(message, category, filename, lineno, module=None, registry=None, module_globals=None, source=None)¶ Il s'agit d'une interface de bas niveau pour la fonctionnalité de
warn()
, en passant explicitement le message, la catégorie, le nom de fichier et le numéro de ligne, et éventuellement le nom du module et le registre (qui devrait être le dictionnaire__warningregistry__
du module). Le nom de module par défaut est le nom de fichier sans.py
; si aucun registre n'est passé, l'avertissement n'est jamais supprimé. message doit être une chaîne de caractères et category une sous-classe deWarning
ou message peut être une instance deWarning
, auquel cas category sera ignoré.module_globals, s'il est fourni, doit être l'espace de nommage global utilisé par le code pour lequel l'avertissement est émis. (Cet argument est utilisé pour afficher les sources des modules trouvés dans les fichiers zip ou d'autres sources d'importation hors du système de fichiers).
source, s'il est fourni, est l'objet détruit qui a émis un
ResourceWarning
.Modifié dans la version 3.6: Ajout du paramètre source.
-
warnings.
showwarning
(message, category, filename, lineno, file=None, line=None)¶ Écrit un avertissement dans un fichier. L'implémentation par défaut appelle
formatwarning(message, category, filename, lineno, line)
et écrit la chaîne résultante dans file, qui par défaut estsys.stderr
. Vous pouvez remplacer cette fonction par n'importe quel appelable en l'affectant àwarnings.showwarning
. line est une ligne de code source à inclure dans le message d'avertissement ; si line n'est pas fourni,showwarning()
essaiera de lire la ligne spécifiée par filename et lineno.
-
warnings.
formatwarning
(message, category, filename, lineno, line=None)¶ Formate un avertissement de la manière standard. Ceci renvoie une chaîne pouvant contenir des retours à la ligne se termine par un retour à la ligne. line est une ligne de code source à inclure dans le message d'avertissement ; si line n'est pas fourni,
formatwarning()
essaiera de lire la ligne spécifiée par filename et lineno.
-
warnings.
filterwarnings
(action, message='', category=Warning, module='', lineno=0, append=False)¶ Insère une entrée dans la liste de warning filter specifications. L'entrée est insérée à l'avant par défaut ; si append est vrai, elle est insérée à la fin. Il vérifie le type des arguments, compile les expressions régulières message et module, et les insère sous forme de tuple dans la liste des filtres d'avertissements. Les entrées plus proches du début de la liste ont priorité sur les entrées plus loin dans la liste. Les arguments omis ont par défaut une valeur qui correspond à tout.
-
warnings.
simplefilter
(action, category=Warning, lineno=0, append=False)¶ Insère une entrée simple dans la liste de spécifications du filtre d'avertissements. La signification des paramètres de fonction est la même que pour
filterwarnings()
, mais les expressions régulières ne sont pas nécessaires car le filtre inséré correspond toujours à n'importe quel message dans n'importe quel module tant que la catégorie et le numéro de ligne correspondent.
-
warnings.
resetwarnings
()¶ Réinitialise le filtre des avertissements. Ceci supprime l'effet de tous les appels précédents à
filterwarnings()
, y compris celui de l'option-W
des options de ligne de commande et des appels àsimplefilter()
.
Gestionnaires de contexte disponibles¶
-
class
warnings.
catch_warnings
(*, record=False, module=None)¶ Un gestionnaire de contexte qui copie et, à la sortie, restaure le filtre des avertissements et la fonction
showwarning()
. Si l'argument record estFalse
(par défaut), le gestionnaire de contexte retourneNone
en entrant. Si record estTrue
, une liste est renvoyée qui est progressivement remplie d'objets comme vus par une fonction customshowwarning' (qui supprime également la sortie vers ``sys.stdout`()
). Chaque objet de la liste a des attributs avec les mêmes noms que les arguments deshowwarning()
.L'argument module prend un module qui sera utilisé à la place du module renvoyé lors de l'importation
warnings
dont le filtre sera protégé. Cet argument existe principalement pour tester le modulewarnings
lui-même.Note
Le gestionnaire
catch_warnings
fonctionne en remplaçant puis en restaurant plus tard la fonctionshowwarning()
du module et la liste interne des spécifications du filtre. Cela signifie que le gestionnaire de contexte modifie l'état global et n'est donc pas prévisible avec plusieurs fils d'exécution.