Maison > développement back-end > Tutoriel Python > Gestion des erreurs professionnelles avec Python

Gestion des erreurs professionnelles avec Python

Jennifer Aniston
Libérer: 2025-03-04 10:58:19
original
375 Les gens l'ont consulté

Dans ce tutoriel, vous apprendrez à gérer les conditions d'erreur dans Python d'un point de vue système entier. La gestion des erreurs est un aspect critique de la conception, et il traverse les niveaux les plus bas (parfois le matériel) jusqu'aux utilisateurs finaux. Si vous avez une stratégie cohérente en place, votre système ne sera pas fiable, l'expérience utilisateur sera médiocre et vous aurez beaucoup de défis à déboguer et à dépanner.

Modèles: codes d'état et exceptions. Les codes d'état peuvent être utilisés par n'importe quel langage de programmation. Les exceptions nécessitent une prise en charge du langage / d'exécution.

Python prend en charge les exceptions. Python et sa bibliothèque standard utilisent généreusement des exceptions pour signaler de nombreuses situations exceptionnelles comme les erreurs IO, diviser par zéro, l'indexation hors limites, et aussi certaines situations pas si exceptionnelles comme la fin de l'itération (bien qu'elle soit cachée). La plupart des bibliothèques suivent le pas et soulèvent des exceptions.

Cela signifie que votre code devra gérer les exceptions soulevées par Python et les bibliothèques de toute façon, vous pouvez donc également augmenter les exceptions à partir de votre code lorsque cela est nécessaire et ne pas compter sur les codes de statut.

Exemple rapide

Avant de plonger dans les exceptions intérieures des exceptions et les exceptions d'erreur, Action:

Voici la sortie lors de l'appel d'appel d'essayer

. Si aucune exception ne se produit, le programme saute la clause Sauf

def f():<br>    return 4 / 0<br>def g():<br>    raise Exception("Don't call us. We'll call you")<br>def h():<br>    try:<br>        f()<br>    except Exception as e:<br>        print(e)<br>    <br>    try:<br>        g()<br>    except Exception as e:<br>        print(e)<br>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Si vous saisissez un numéro entier, le programme fonctionne comme prévu. Cependant, si vous entrez un flotteur ou une chaîne, le programme cesse de s'exécuter.

Lorsque vous prenez une exception, vous avez trois options:

Please enter a number: 10.3<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: hello<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: 10.0<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: <br>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Avalez-la tranquille Original.

    Avalez l'exception
  • Vous devez avaler l'exception si vous savez comment le gérer et que vous pouvez récupérer complètement.
  • Par exemple, si vous recevez un fichier d'entrée qui peut être sous différents formats (JSON, YAML), vous pouvez essayer de le analyser en utilisant différents analyseurs. Si le Parser JSON a soulevé une exception que le fichier n'est pas un fichier JSON valide, vous l'avalez et essayez avec l'analyseur YAML. Si l'analyseur YAML a également échoué, vous laissez l'exception se propager.
Notez que d'autres exceptions (par exemple, le fichier non trouvé ou aucune lecture) se propagera et ne sera pas capturé par la clause spécifique sauf. Ceci est une bonne politique dans ce cas où vous souhaitez essayer l'analyse YAML uniquement si l'analyse JSON a échoué en raison d'un problème de codage JSON.

Si vous souhaitez gérer

toutes les exceptions

alors utilisez simplement sauf l'exception <p>. Par exemple: </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">def f():&lt;br&gt; return 4 / 0&lt;br&gt;def g():&lt;br&gt; raise Exception(&quot;Don't call us. We'll call you&quot;)&lt;br&gt;def h():&lt;br&gt; try:&lt;br&gt; f()&lt;br&gt; except Exception as e:&lt;br&gt; print(e)&lt;br&gt; &lt;br&gt; try:&lt;br&gt; g()&lt;br&gt; except Exception as e:&lt;br&gt; print(e)&lt;br&gt;</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div> <p> Notez qu'en ajoutant <code>as e, vous liez l'objet d'exception au nom e disponible dans votre clause expressive.

Remontez à nouveau la même exception

pour relever l'exception, ajoutez simplement raise sans arguments à l'intérieur de votre gestionnaire. Cela vous permet d'effectuer une manipulation locale, mais permet toujours aux niveaux supérieurs de le gérer également. Ici, la fonction invoke_function() imprime le type d'exception à la console, puis soulève à nouveau l'exception.

Please enter a number: 10.3<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: hello<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: 10.0<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: <br>
Copier après la connexion
Copier après la connexion
Copier après la connexion

, soulève une exception différente

Il y a plusieurs cas où vous voudriez lever une exception différente. Parfois, vous souhaitez regrouper plusieurs exceptions de bas niveau dans une seule catégorie qui est gérée uniformément par code de niveau supérieur. Dans les cas, vous devez transformer l'exception au niveau de l'utilisateur et fournir un contexte spécifique à l'application.

Enfin la clause

Parfois, vous souhaitez vous assurer qu'un code de nettoyage s'exécute même si une exception a été soulevée quelque part en cours de route. Par exemple, vous pouvez avoir une connexion de base de données que vous souhaitez fermer une fois que vous avez terminé. Voici la mauvaise façon de le faire:

import json<br>import yaml<br><br>def parse_file(filename):<br>    try:<br>        return json.load(open(filename))<br>    except json.JSONDecodeError<br>        return yaml.load(open(filename))<br>
Copier après la connexion
Copier après la connexion

Si la fonction query() soulève une exception, alors l'appel à close_db_connection() ne s'exécutera jamais et que la connexion DB restera ouverte. La clause finally s'exécute toujours après l'exécution de tout le gestionnaire d'exceptions. Voici comment le faire correctement:

def print_exception_type(func, *args, **kwargs):<br>    try:<br>        return func(*args, **kwargs)<br>    except Exception as e:<br>        print(type(e))<br>
Copier après la connexion

L'appel à open_db_connection() peut ne pas renvoyer une connexion ou augmenter une exception elle-même. Dans ce cas, il n'est pas nécessaire de fermer la connexion DB.

Lorsque vous utilisez finally, vous devez faire attention de ne pas y soulever d'exceptions car ils masqueront l'exception d'origine.

Les gestionnaires de contexte

Les gestionnaires de contexte fournissent un autre mécanisme pour envelopper des ressources telles que les fichiers ou les connexions DB dans le code de nettoyage qui s'exécute automatiquement lorsque des exceptions ont été soulevées. Au lieu de blocs d'essai, vous utilisez l'instruction with. Voici un exemple avec un fichier:

def invoke_function(func, *args, **kwargs):<br>    try:<br>        return func(*args, **kwargs)<br>    except Exception as e:<br>        print(type(e))<br>        raise<br>
Copier après la connexion

Maintenant, même si process() a soulevé une exception, le fichier sera fermé correctement immédiatement lorsque la portée du bloc with est sortie, que l'exception soit gérée ou non. Il est particulièrement utile dans les applications Web où vous pouvez traiter toutes les exceptions de manière générique: enregistrez simplement l'exception et renvoyez un message d'erreur à l'appelant.

Lors de la journalisation, il est utile de journaliser le type d'exception, le message d'erreur et le StackTrace. Toutes ces informations sont disponibles via l'objet

, mais si vous utilisez la méthode

dans votre gestionnaire d'exceptions, le système de journalisation Python extraire toutes les informations pertinentes pour vous.

C'est la meilleure pratique que je recommande:

def f():<br>    return 4 / 0<br>def g():<br>    raise Exception("Don't call us. We'll call you")<br>def h():<br>    try:<br>        f()<br>    except Exception as e:<br>        print(e)<br>    <br>    try:<br>        g()<br>    except Exception as e:<br>        print(e)<br>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Si vous suivez ce modèle, alors (en supposant que vous configurez correctement la connexion), peu importe ce qui se passe, vous aurez un très bon enregistrement dans vos journaux de ce qui ne va pas, et vous pourrez à nouveau résoudre le même problème. C'est un gaspillage, et cela pourrait vous confondre et vous faire penser que plusieurs instances du même problème se sont produites, alors qu'en pratique une seule instance a été enregistrée plusieurs fois.

La façon la plus simple de le faire est de laisser toutes les exceptions se propager (sauf si elles peuvent être manipulées en toute confiance et avalée plus tôt) et ensuite faire le journal proche de votre niveau supérieur de votre votre application / système.

Sentry

La journalisation est une capacité. L'implémentation la plus courante consiste à utiliser des fichiers journaux. Mais, pour les systèmes distribués à grande échelle avec des centaines, des milliers ou plus de serveurs, ce n'est pas toujours la meilleure solution.

Pour garder une trace des exceptions dans toute votre infrastructure, un service comme Sentry est super utile. Il centralise tous les rapports d'exception, et en plus de la stackTrace, il ajoute l'état de chaque trame de pile (la valeur des variables au moment où l'exception a été soulevée). Il fournit également une très belle interface avec des tableaux de bord, des rapports et des moyens de décomposer les messages par plusieurs projets. Il est open source, vous pouvez donc exécuter votre propre serveur ou vous abonner à la version hébergée.

Vous trouverez ci-dessous une capture d'écran montrant comment Sentry présente les erreurs de votre application Python.

Et voici une trace de pile détaillée du fichier provoquant l'erreur. Gestion des erreurs professionnelles avec Python

Certains échecs sont temporaires, dans l'erreur. Un système qui panique au premier signe de problème n'est pas très utile. Gestion des erreurs professionnelles avec Python

Si votre code accéde à un système distant qui ne répond pas, la solution traditionnelle est des délais d'attente, mais parfois tous les systèmes ne sont pas conçus avec des délais d'attente. Les délais d'expiration ne sont pas toujours faciles à calibrer à mesure que les conditions changent.

Une autre approche consiste à échouer rapidement, puis à réessayer. L'avantage est que si la cible répond rapidement, vous n'avez pas à passer beaucoup de temps en état de sommeil et que vous pouvez réagir immédiatement. Mais s'il a échoué, vous pouvez réessayer plusieurs fois jusqu'à ce que vous décidiez qu'il est vraiment inaccessible et augmente une exception. Dans la section suivante, je présenterai un décorateur qui peut le faire pour vous.

décorateurs utiles

Deux décorateurs qui peuvent aider à la manipulation des erreurs sont les

, qui enregistrera une exception puis le soulève à nouveau, et le

décorateur, qui se rétrativra à plusieurs reprises une fonction. @log_error

Erreur Logger

Voici une simple implémentation. Le décorateur sauf un objet d'enregistrement. Lorsqu'il décore une fonction et que la fonction est invoquée, elle enveloppera l'appel dans une clause d'essai à l'exception, et s'il y a eu une exception, il le enregistrera et augmentera enfin l'exception à nouveau.

def f():<br>    return 4 / 0<br>def g():<br>    raise Exception("Don't call us. We'll call you")<br>def h():<br>    try:<br>        f()<br>    except Exception as e:<br>        print(e)<br>    <br>    try:<br>        g()<br>    except Exception as e:<br>        print(e)<br>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Voici comment l'utiliser:

Please enter a number: 10.3<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: hello<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: 10.0<br>Oops!  That was no valid number.  Try again...<br>Please enter a number: <br>
Copier après la connexion
Copier après la connexion
Copier après la connexion

Recrier

Voici une très bonne implémentation de @retry décorateur.

import json<br>import yaml<br><br>def parse_file(filename):<br>    try:<br>        return json.load(open(filename))<br>    except json.JSONDecodeError<br>        return yaml.load(open(filename))<br>
Copier après la connexion
Copier après la connexion

Conclusion

La gestion des erreurs est cruciale pour les utilisateurs et les développeurs. Python fournit un excellent support dans la langue et la bibliothèque standard pour la gestion des erreurs basée sur des exceptions. En suivant avec diligence les meilleures pratiques, vous pouvez conquérir cet aspect souvent négligé.

Ce message a été mis à jour avec les contributions d'Esther Vaati. Esther est un développeur de logiciels et écrivain pour Envato TUTS.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal