Maison >développement back-end >Tutoriel Python >Gestion des erreurs professionnelles avec Python
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.
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:
. 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>
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>Avalez-la tranquille Original.
toutes les exceptions
alors utilisez simplement sauf l'exception <p>. Par exemple: </p>
<pre class="brush:php;toolbar:false">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></pre> <p> Notez qu'en ajoutant <code>as e
, vous liez l'objet d'exception au nom e
disponible dans votre clause expressive. 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>
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.
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>
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>
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 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>
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.
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>
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
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.
Certains échecs sont temporaires, dans l'erreur. Un système qui panique au premier signe de problème n'est pas très utile.
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
décorateur, qui se rétrativra à plusieurs reprises une fonction. @log_error
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>
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>
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>
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!