Comprendre le traçage Python – Real Python

By | juillet 29, 2019

Formation Python

Python imprime un traceback lorsqu'une exception est levée dans votre code. La sortie de trace peut être un peu lourde si vous la voyez pour la première fois ou si vous ne savez pas ce qu’elle vous dit. Mais le suivi Python contient une mine d'informations qui peuvent vous aider à diagnostiquer et à résoudre le motif de l'exception générée dans votre code. Comprendre les informations fournies par une trace Python est essentiel pour devenir un meilleur programmeur Python.

À la fin de ce didacticiel, vous pourrez:

  • Donner un sens à la prochaine trace que vous voyez
  • Reconnaître certaines des traces les plus courantes
  • Enregistrer un suivi avec succès tout en maintenant l'exception

Qu'est-ce qu'un Traceback Python?

Une trace est un rapport contenant les appels de fonction effectués dans votre code à un moment donné. Les tracés sont connus sous plusieurs noms, y compris trace de la pile, trace de pile, la traceet peut-être d'autres. En Python, le terme utilisé est traceback.

Lorsque votre programme génère une exception, Python imprimera le traçage actuel pour vous aider à déterminer ce qui ne va pas. Voici un exemple pour illustrer cette situation:

# exemple.py
def saluer(Quelqu'un):
    impression('Bonjour, ' + quelqu'un)

saluer('Chad')

Ici, saluer() est appelé avec le paramètre Quelqu'un. Cependant, dans saluer(), ce nom de variable n’est pas utilisé. Au lieu de cela, il a été mal orthographié quelqu'un dans le impression() appel.

Lorsque vous exécutez ce programme, vous obtenez le suivi suivant:

$ python exemple.py
Traceback (dernier appel le plus récent):
        Fichier "/path/to/example.py", ligne 4, dans 
                saluer ('Chad')
        Fichier "/path/to/example.py", ligne 2, dans message d'accueil
                print ('Bonjour', quelque chose)
NameError: le nom 'someon' n'est pas défini

Cette sortie de suivi contient toutes les informations dont vous aurez besoin pour diagnostiquer le problème. La dernière ligne de la sortie de traceback vous indique le type d'exception levée ainsi que des informations pertinentes sur cette exception. Les lignes précédentes du suivi soulignent le code qui a provoqué la levée de l'exception.

Dans la trace ci-dessus, l’exception était une NameError, ce qui signifie qu’il y a une référence à un nom (variable, fonction, classe) qui n’a pas été défini. Dans ce cas, le nom référencé est quelqu'un.

La dernière ligne dans ce cas contient suffisamment d'informations pour vous aider à résoudre le problème. Recherche du code pour le nom quelqu'un, qui est une faute d’orthographe, vous orientera dans la bonne direction. Cependant, votre code est souvent beaucoup plus compliqué.

Comment lisez-vous un Traceback Python?

Le suivi Python contient de nombreuses informations utiles lorsque vous essayez de déterminer la raison d’une exception générée dans votre code. Dans cette section, vous allez parcourir différentes traces en arrière afin de comprendre les différentes informations contenues dans une trace.

Vue d'ensemble du traçage Python

Il existe plusieurs sections importantes pour chaque traceback Python. Le schéma ci-dessous met en évidence les différentes parties:

Un exemple de trace Python avec des appels.

En Python, il est préférable de lire la trace de bas en haut:

  1. Boite bleue: La dernière ligne de la trace est la ligne du message d'erreur. Il contient le nom de l'exception qui a été levée.

  2. Boîte verte: Après le nom de l'exception est le message d'erreur. Ce message contient généralement des informations utiles pour comprendre la raison de la levée de l'exception.

  3. Boîte jaune: Plus haut dans la trace, les différents appels de fonction se déplacent de bas en haut, du plus récent au moins récent. Ces appels sont représentés par des entrées de deux lignes pour chaque appel. La première ligne de chaque appel contient des informations telles que le nom du fichier, le numéro de la ligne et le nom du module, spécifiant toutes où le code peut être trouvé.

  4. Souligné en rouge: La deuxième ligne de ces appels contient le code qui a été exécuté.

Il existe quelques différences entre la sortie de traceback lorsque vous exécutez votre code dans la ligne de commande et le code en cours d’exécution dans la réplique. Ci-dessous se trouve le même code de la section précédente exécutée dans un REPL et la sortie de trace résultante:

>>>

>>> def saluer(Quelqu'un):
...   impression('Bonjour, ' + quelqu'un)
... 
>>> saluer('Chad')
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
  
  
  
  Fichier "", ligne 2, dans saluer
NameError: le nom 'quelqu'un' n'est pas défini

Notez qu'au lieu de noms de fichiers, vous obtenez "". Cela a du sens puisque vous avez saisi le code via une entrée standard. En outre, les lignes de code exécutées ne sont pas affichées dans le suivi.

Procédure pas à pas spécifique

Le fait de parcourir certaines sorties de traceback vous aidera à mieux comprendre et à voir quelles informations le traceback vous donnera.

Le code ci-dessous est utilisé dans les exemples suivants pour illustrer les informations fournies par un suivi Python:

# greetings.py
def who_to_greet(la personne):
    revenir la personne si la personne autre contribution('Salut à qui? ')

def saluer(Quelqu'un, salutation='Bonjour'):
    impression(salutation + ',' + who_to_greet(Quelqu'un))

def salut_many(personnes):
    pour la personne dans personnes:
        essayer:
            saluer(la personne)
        sauf Exception:
            impression('salut, ' + la personne)

Ici, who_to_greet () prend une valeur, la personne, et le renvoie ou invite une valeur à renvoyer à la place.

Ensuite, saluer() prend un nom pour être salué, Quelqu'unet une option salutation valeur et appels impression(). who_to_greet () est aussi appelé avec le Quelqu'un valeur transmise.

Finalement, greet_many () ira sur la liste des personnes et appeler saluer(). Si une exception est déclenchée en appelant saluer(), un simple message d'accueil de sauvegarde est alors imprimé.

Ce code ne contient aucun bogue susceptible de générer une exception tant que la bonne entrée est fournie.

Si vous ajoutez un appel à saluer() au fond de salutations.py et spécifiez un argument de mot-clé inattendu (par exemple, saluer ('Chad', greting = 'Yo')), vous obtiendrez le suivi suivant:

$ python exemple.py
Traceback (dernier appel le plus récent):
        Fichier "/path/to/greetings.py", ligne 19, dans 
                saluer ('Chad', greting = 'Yo')
TypeError: greet () a un argument de mot clé inattendu 'greting'

Une fois encore, avec un suivi Python, il est préférable de revenir en arrière, en remontant la sortie. À partir de la dernière ligne du traçage, vous pouvez voir que l’exception était une Erreur-type. Les messages qui suivent le type d'exception, tout ce qui suit le côlon, vous fournissent d'excellentes informations. Il vous dit que saluer() a été appelé avec un argument de mot-clé auquel il ne s’attendait pas. Le nom de l'argument inconnu vous est également donné: greting.

En montant, vous pouvez voir la ligne qui a abouti à l'exception. Dans ce cas, c’est le saluer() appelons cela, nous avons ajouté au bas de salutations.py.

La ligne suivante vous indique le chemin d'accès au fichier contenant le code, le numéro de la ligne où ce code peut être trouvé et le module dans lequel il se trouve. Dans ce cas, notre code n'utilise aucun autre module Python. , on vient de voir ici, ce qui signifie que c'est le fichier en cours d'exécution.

Avec un fichier différent et une entrée différente, vous pouvez voir le traçage vous orienter vraiment dans la bonne direction pour trouver le problème. Si vous suivez, supprimez le buggy saluer() appel du bas de salutations.py et ajoutez le fichier suivant à votre répertoire:

# exemple.py
de salutations importation saluer

saluer(1)

Ici vous avez configuré un autre fichier Python qui importe votre module précédent, salutations.pyet en utilisant saluer() à partir de cela. Voici ce qui se passe si vous exécutez maintenant exemple.py:

$ python exemple.py
Traceback (dernier appel le plus récent):
        Fichier "/path/to/example.py", ligne 3, dans 
                saluer (1)
        Fichier "/path/to/greetings.py", ligne 5, dans message d'accueil
                print (salutation + ',' + who_to_greet (quelqu'un))
TypeError: doit être str, pas int

L'exception soulevée dans ce cas est un Erreur-type encore une fois, mais cette fois le message est un peu moins utile. Il vous dit que quelque part dans le code, il s'attendait à travailler avec une chaîne, mais un entier a été donné.

En montant, vous voyez la ligne de code qui a été exécutée. Puis le fichier et le numéro de ligne du code. Cette fois, cependant, au lieu de , nous obtenons le nom de la fonction en cours d'exécution, saluer().

En passant à la prochaine ligne de code exécutée, nous voyons notre problématique saluer() appel passant dans un entier.

Parfois, après la levée d'une exception, un autre morceau de code intercepte cette exception et génère également une exception. Dans ces situations, Python générera tous les retraits d’exception dans l’ordre dans lequel ils ont été reçus, se terminant à nouveau par le dernier retraçage de l’exception.

Comme cela peut être un peu déroutant, voici un exemple. Ajouter un appel à greet_many () au fond de salutations.py:

# greetings.py
...
salut_many([[[['Chad', 'Dan', 1])

Cela devrait donner lieu à des salutations aux trois personnes. Toutefois, si vous exécutez ce code, vous verrez un exemple de plusieurs retraits de trace en cours de sortie:

$ python salutations.py
Bonjour tchad
Bonjour Dan
Traceback (dernier appel le plus récent):
        Fichier "greetings.py", ligne 10, dans greet_many
                saluer (personne)
        Fichier "greetings.py", ligne 5, dans greet
                print (salutation + ',' + who_to_greet (quelqu'un))
TypeError: doit être str, pas int

Lors du traitement de l'exception ci-dessus, une autre exception s'est produite:

Traceback (dernier appel le plus récent):
        Fichier "greetings.py", ligne 14, dans 
                greet_many (['Chad', 'Dan', 1])
        Fichier "greetings.py", ligne 12, dans greet_many
                print ('salut' + personne)
TypeError: doit être str, pas int

Notez la ligne en surbrillance commençant par Pendant la manutention dans la sortie ci-dessus. Entre toutes les traces, vous verrez cette ligne. Son message est très clair, alors que votre code essayait de gérer l’exception précédente, une autre exception était levée.

Vous avez déjà vu l’exception précédente lorsque vous avez appelé saluer() avec un entier. Depuis que nous avons ajouté un 1 à la liste des personnes à saluer, on peut s'attendre au même résultat. Cependant, la fonction greet_many () enveloppe le saluer() appeler dans un essayer et sauf bloc. Au cas où saluer() résulte en une exception levée, greet_many () veut imprimer un message d'accueil par défaut.

La partie pertinente de salutations.py est répété ici:

def salut_many(personnes):
    pour la personne dans personnes:
        essayer:
            saluer(la personne)
        sauf Exception:
            impression('salut, ' + la personne)

Donc quand saluer() résultats dans le Erreur-type à cause de la mauvaise entrée entière, greet_many () gère cette exception et tente d’imprimer un message d'accueil simple. Ici, le code aboutit à une autre exception similaire. Il tente toujours d’ajouter une chaîne et un entier.

Voir toute la sortie de traceback peut vous aider à voir quelle peut être la cause réelle d'une exception. Parfois, lorsque vous voyez la dernière exception déclenchée et son suivi, vous ne pouvez toujours pas voir ce qui ne va pas. Dans ces cas, le passage aux exceptions précédentes vous donne généralement une meilleure idée de la cause première.

Quels sont les traçages courants en Python?

Savoir comment lire une trace Python lorsque votre programme lève une exception peut être très utile lorsque vous programmez, mais connaître certaines des traces les plus courantes peut également accélérer votre processus.

Voici quelques exceptions courantes que vous pourriez rencontrer, les raisons pour lesquelles elles ont été soulevées, leur signification et les informations que vous pouvez trouver dans leurs retraits.

AttributeError

le AttributeError est déclenchée lorsque vous essayez d'accéder à un attribut sur un objet pour lequel cet attribut n'a pas été défini. La documentation Python définit le moment où cette exception est déclenchée:

Relevé lorsqu'une référence d'attribut ou une attribution échoue. (La source)

Voici un exemple de AttributeError être élevé:

>>>

>>> an_int = 1
>>> an_int.un_attribut
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
AttributeError: L'objet 'int' n'a pas d'attribut 'an_attribute'

La ligne de message d'erreur pour un AttributeError vous indique que le type d'objet spécifique, int dans ce cas, l’attribut n’a pas été accédé, un_attribut dans ce cas. Voyant le AttributeError dans la ligne de message d'erreur peut vous aider à identifier rapidement l'attribut auquel vous avez tenté d'accéder et où aller pour le corriger.

Généralement, obtenir cette exception indique que vous travaillez probablement avec un objet d'un type différent de celui que vous attendiez:

>>>

>>> une liste = (1, 2)
>>> une liste.ajouter(3)
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
AttributeError: L'objet 'tuple' n'a pas d'attribut 'append'

Dans l'exemple ci-dessus, vous pourriez vous attendre à une liste être de type liste, qui a une méthode appelée .ajouter(). Quand vous recevez le AttributeError exception et voir qu'il a été soulevé lorsque vous essayez d'appeler .ajouter(), cela vous indique que vous n’avez probablement pas affaire au type d’objet que vous attendiez.

Cela se produit souvent lorsque vous vous attendez à ce qu'un objet renvoyé par un appel de fonction ou de méthode soit d'un type spécifique et que vous vous retrouviez avec un objet de type. Aucun. Dans ce cas, la ligne du message d'erreur sera lue, AttributeError: l'objet 'NoneType' n'a pas d'attribut 'append'.

ImportError

le ImportError est levé quand quelque chose ne va pas avec une déclaration d'importation. Vous obtiendrez cette exception, ou sa sous-classe ModuleNotFoundErrorsi le module que vous essayez d’importer est introuvable ou si vous essayez d’importer quelque chose d’un module qui n’existe pas dans le module. La documentation Python définit le moment où cette exception est déclenchée:

Relevé lorsque l'instruction d'importation rencontre des difficultés lors du chargement d'un module. Également soulevé lorsque le «à partir de la liste» dans de ... import a un nom qui ne peut pas être trouvé. (La source)

Voici un exemple de ImportError et ModuleNotFoundError être élevé:

>>>

>>> importation asdf
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
ModuleNotFoundError: Aucun module nommé 'asdf'
>>> de collections importation asdf
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
ImportError: ne peut pas importer le nom 'asdf'

Dans l'exemple ci-dessus, vous pouvez voir que tenter d'importer un module qui n'existe pas, asdf, résultats dans le ModuleNotFoundError. Lorsqu’on tente d’importer quelque chose qui n’existe pas, asdf, à partir d'un module qui existe, collections, il en résulte une ImportError. Les lignes de message d’erreur au bas de la trace vous indiquent ce qui ne peut pas être importé, asdf dans les deux cas.

IndexError

le IndexError est levé lorsque vous essayez de récupérer un index à partir d'une séquence, comme un liste ou un tupleet l’index ne figure pas dans la séquence. La documentation Python définit le moment où cette exception est déclenchée:

Relevé lorsqu'un indice de séquence est hors limites. (La source)

Voici un exemple qui soulève la IndexError:

>>>

>>> une liste = [[[['une', 'b']
>>> une liste[[[[3]
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
IndexError: index de liste hors de portée

La ligne de message d'erreur pour un IndexError ne vous donne pas d'excellentes informations. Vous pouvez voir que vous avez une référence de séquence qui est hors de portée et quel est le type de la séquence, un liste dans ce cas. Ces informations, associées au reste de la trace, sont généralement suffisantes pour vous aider à identifier rapidement comment résoudre le problème.

KeyError

Semblable à la IndexError, la KeyError est déclenchée lorsque vous essayez d’accéder à une clé qui ne figure pas dans le mappage, généralement une clé. dict. Pensez à cela comme à la IndexError mais pour les dictionnaires. La documentation Python définit le moment où cette exception est déclenchée:

Relevé lorsqu'une clé de mappage (dictionnaire) est introuvable dans l'ensemble de clés existantes. (La source)

Voici un exemple de KeyError être élevé:

>>>

>>> un_dict[[[['b']
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
KeyError: 'b'

La ligne de message d'erreur pour un KeyError vous donne la clé qui n'a pas pu être trouvée. Ce n’est pas grand-chose à faire, mais, combiné avec le reste de la trace, suffit généralement à résoudre le problème.

Pour un regard en profondeur sur KeyError, consultez les exceptions Python KeyError et Comment les gérer.

NameError

le NameError est déclenché lorsque vous avez référencé une variable, un module, une classe, une fonction ou un autre nom qui n’a pas été défini dans votre code. La documentation Python définit le moment où cette exception est déclenchée:

Relevé lorsqu'un nom local ou global n'est pas trouvé. (La source)

Dans le code ci-dessous, saluer() prend un paramètre la personne. Mais dans la fonction elle-même, ce paramètre a été mal orthographié persn:

>>>

>>> def saluer(la personne):
...     impression(F'Bonjour, persn')
>>> saluer('Monde')
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
  
  
  
  Fichier "", ligne 2, dans saluer
NameError: nom 'persn' n'est pas défini

La ligne de message d'erreur du NameError traceback vous donne le nom qui manque. Dans l'exemple ci-dessus, il s'agit d'une variable ou d'un paramètre mal orthographié pour la fonction transmise.

UNE NameError sera également levé si c’est le paramètre que vous avez mal orthographié:

>>>

>>> def saluer(persn):
...     impression(F'Bonjour, la personne')
>>> saluer('Monde')
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
  
  
  
  Fichier "", ligne 2, dans saluer
NameError: nom 'personne' n'est pas défini

Ici, on pourrait croire que vous n’avez rien fait de mal. La dernière ligne exécutée et référencée dans le suivi semble bonne. Si vous vous trouvez dans cette situation, vous devez alors regarder dans votre code pour savoir où la personne la variable est utilisée et définie. Ici, vous pouvez rapidement voir que le nom du paramètre a été mal orthographié.

Erreur de syntaxe

le Erreur de syntaxe est déclenché lorsque vous avez une syntaxe Python incorrecte dans votre code. La documentation Python définit le moment où cette exception est déclenchée:

Lancé lorsque l'analyseur rencontre une erreur de syntaxe. (La source)

Ci-dessous, le problème est un colon manquant qui devrait se trouver à la fin de la ligne de définition de la fonction. Dans le REPL Python, cette erreur de syntaxe est immédiatement générée après avoir tapé, entrez:

>>>

>>> def saluer(la personne)
  Fichier "", ligne 1
    def saluer(la personne)
                    ^
Erreur de syntaxe: Syntaxe invalide

La ligne de message d'erreur du Erreur de syntaxe vous dit seulement qu'il y avait un problème avec la syntaxe de votre code. En regardant dans les lignes ci-dessus, vous voyez la ligne avec le problème et généralement un ^ (Caret) montrant le point du problème. Ici, le côlon est absent de la fonction def déclaration.

Aussi, avec Erreur de syntaxe tracebacks, la première ligne régulière Traceback (dernier appel le plus récent): est manquant. C'est parce que le Erreur de syntaxe est levé lorsque Python tente d’analyser votre code et que les lignes ne sont pas en cours d’exécution.

Erreur-type

le Erreur-type est déclenchée lorsque votre code tente de faire quelque chose avec un objet qui ne peut pas le faire, comme essayer d’ajouter une chaîne à un entier ou d’appeler len () sur un objet où sa longueur n’est pas définie. La documentation Python définit le moment où cette exception est déclenchée:

Relevé lorsqu'une opération ou une fonction est appliquée à un objet de type inapproprié. (La source)

Voici plusieurs exemples de Erreur-type être élevé:

>>>

>>> 1 + '1'
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
Erreur-type: type (s) d'opérande non pris en charge pour +: 'int' et 'str'
>>> '1' + 1
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
Erreur-type: doit être str, pas int
>>> len(1)
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
Erreur-type: l'objet de type 'int' n'a pas de len ()

Tous les exemples ci-dessus d’élever un Erreur-type résulte en une ligne de message d'erreur avec des messages différents. Chacun d'eux fait un très bon travail pour vous informer de ce qui ne va pas.

Les deux premiers exemples tentent d'ajouter des chaînes et des entiers. Cependant, ils sont légèrement différents:

  • Le premier essaie d’ajouter un str à un int.
  • La seconde tente d’ajouter un int à un str.

Les lignes de message d'erreur reflètent ces différences.

Le dernier exemple tente d'appeler len () sur un int. Le message d'erreur vous indique que vous ne pouvez pas le faire avec un int.

ValueError

le ValueError est levé lorsque la valeur de l'objet n'est pas correcte. Vous pouvez penser à cela comme un IndexError est élevé car la valeur de l’index n’est pas dans la plage de la séquence, seule la valeur ValueError est pour un cas plus générique. La documentation Python définit le moment où cette exception est déclenchée:

Lancé lorsqu'une opération ou une fonction reçoit un argument qui a le bon type, mais une valeur inappropriée, et la situation n'est pas décrite par une exception plus précise, telle que IndexError. (La source)

Voici deux exemples de ValueError être élevé:

>>>

>>> une, b, c = [[[[1, 2]
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
ValueError: pas assez de valeurs pour décompresser (attendu 3, 2)
>>> une, b = [[[[1, 2, 3]
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
ValueError: trop de valeurs à décompresser (attendu 2)

le ValueError La ligne de message d'erreur dans ces exemples vous indique exactement quel est le problème avec les valeurs:

  1. Dans le premier exemple, vous essayez de décompresser trop de valeurs. La ligne de message d'erreur vous indique même que vous vous attendiez à décompresser 3 valeurs mais 2 valeurs.

  2. Dans le deuxième exemple, le problème est que vous obtenez trop de valeurs et pas assez de variables pour les décompresser.

Comment vous enregistrez un traçage?

L'obtention d'une exception et de son suivi Python résultant signifie que vous devez décider quoi faire à ce sujet. La correction de votre code est généralement la première étape, mais parfois le problème provient d'une saisie inattendue ou incorrecte. Bien qu'il soit bon de prévoir ces situations dans votre code, il est également parfois judicieux de faire taire ou de masquer l'exception en enregistrant le suivi et en faisant autre chose.

Voici un exemple de code plus réel qui doit faire taire certaines traces de retour Python. Cet exemple utilise le demandes bibliothèque. Vous pouvez en savoir plus à ce sujet dans la bibliothèque de requêtes de Python (Guide):

# urlcaller.py
importation sys
importation demandes

réponse = demandes.obtenir(sys.argv[[[[1])

impression(réponse.status_code, réponse.contenu)

Ce code fonctionne bien. Lorsque vous exécutez ce script en lui attribuant une URL sous forme d'argument de ligne de commande, il appelle l'URL, puis imprime le code d'état HTTP et le contenu de la réponse. Cela fonctionne même si la réponse était un statut d'erreur HTTP:

$ python urlcaller.py https://httpbin.org/status/200
200 b ''
$ python urlcaller.py https://httpbin.org/status/500
500 b ''

Cependant, il arrive parfois que l’URL que votre script doit récupérer n’existe pas ou que le serveur hôte soit en panne. Dans ces cas, ce script va maintenant soulever un problème Erreur de connexion exception et imprimer une traceback:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
...
Lors du traitement de l'exception ci-dessus, une autre exception s'est produite:

Traceback (dernier appel le plus récent):
        Fichier "urlcaller.py", ligne 5, dans 
    réponse = demandes.obtenir(sys.argv[[[[1])
        Fichier "/path/to/requests/api.py", ligne 75, dans obtenir
    revenir demande('obtenir', url, params=params, **Kwargs)
  Fichier "/path/to/requests/api.py", ligne 60, dans demande
    revenir session.demande(méthode=méthode, url=url, **Kwargs)
  Fichier "/path/to/requests/sessions.py", ligne 533, dans demande
    resp = soi.envoyer(préparation, **send_kwargs)
  Fichier "/path/to/requests/sessions.py", ligne 646, dans envoyer
    r = adaptateur.envoyer(demande, **Kwargs)
  Fichier "/path/to/requests/adapters.py", ligne 516, dans envoyer
    élever Erreur de connexion(e, demande=demande)
requests.exceptions.ConnectionError: HTTPConnectionPool (host = 'thisurlprobablydoesntexist.com', port = 80): Nombre maximal de nouvelles tentatives dépassé avec l'URL: / (provoqué par NewConnectionError (': Impossible d'établir une nouvelle connexion: [Errno -2] Nom ou service non connu ',))

Le traceback Python peut être très long, avec beaucoup d’autres exceptions levées et aboutissant finalement à la Erreur de connexion être élevé par demandes lui-même. Si vous remontez le dernier retraçage des exceptions, vous pouvez voir que le problème a commencé dans notre code avec la ligne 5 de urlcaller.py.

Si vous emballez la ligne incriminée dans un essayer et sauf block, attraper l'exception appropriée permettra à votre script de continuer à fonctionner avec plus d'entrées:

# urlcaller.py
...
essayer
    réponse = demandes.obtenir(sys.argv[[[[1])
sauf demandes.exceptions.Erreur de connexion:
    impression(-1, 'Erreur de connexion')
autre:
    impression(réponse.status_code, réponse.contenu)

Le code ci-dessus utilise un autre clause avec le essayer et sauf bloc. Si vous ne connaissez pas cette fonctionnalité de Python, consultez la section sur la autre clause dans Python Exceptions: An Introduction.

Maintenant, lorsque vous exécutez le script avec une URL qui entraînera une Erreur de connexion être élevé, vous aurez imprimé un -1 pour le code d'état et le contenu Erreur de connexion:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
-1 erreur de connexion

Cela fonctionne très bien. Cependant, dans la plupart des systèmes réels, vous ne souhaitez pas simplement faire taire l'exception et la trace résultante, mais vous souhaitez consigner la trace. La journalisation des traces vous permet de mieux comprendre ce qui ne va pas dans vos programmes.

Vous pouvez enregistrer le suivi dans le script en important le enregistrement package, obtenir un enregistreur et appeler .exception() sur cet enregistreur dans le sauf partie de la essayer et sauf bloc. Votre script final devrait ressembler au code suivant:

# urlcaller.py
importation enregistrement
importation sys
importation demandes

enregistreur = enregistrement.getLogger(__prénom__)

essayer:
    réponse = demandes.obtenir(sys.argv[[[[1])
sauf demandes.exceptions.Erreur de connexion comme e:
    enregistreur.exception()
    impression(-1, 'Erreur de connexion')
autre:
    impression(réponse.status_code, réponse.contenu)

Maintenant, lorsque vous exécutez le script pour une URL problématique, il imprimera le résultat attendu. -1 et Erreur de connexion, mais cela enregistrera également le suivi:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
...
  Fichier "/path/to/requests/adapters.py", ligne 516, dans envoyer
    élever Erreur de connexion(e, demande=demande)
requests.exceptions.ConnectionError: HTTPConnectionPool (host = 'thisurlprobablydoesntexist.com', port = 80): Nombre maximal de nouvelles tentatives dépassé avec l'URL: / (provoqué par NewConnectionError (': Impossible d'établir une nouvelle connexion: [Errno -2] Nom ou service non connu ',))
-1 erreur de connexion

Par défaut, Python enverra les messages de journal à l'erreur standard (stderr). On dirait que nous n’avons pas du tout supprimé la sortie de trace. Toutefois, si vous appelez à nouveau tout en redirigeant le stderr, vous pouvez voir que le système de journalisation fonctionne et que nous pouvons sauvegarder nos journaux pour plus tard:

$ python urlcaller.py http://thisurlprobablydoesntexist.com 2> mon-logs.log
-1 erreur de connexion

Conclusion

Le suivi Python contient d'excellentes informations qui peuvent vous aider à trouver ce qui ne va pas dans votre code Python. Ces retraits peuvent sembler un peu intimidants, mais une fois que vous avez analysé ce que vous essayez de vous montrer, ils peuvent être extrêmement utiles. En parcourant quelques traces en arrière, ligne par ligne, vous comprendrez mieux les informations qu’elles contiennent et vous en tirerez le meilleur parti.

Obtenir une sortie de trace Python lorsque vous exécutez votre code est une opportunité d'améliorer votre code. C’est l’une des façons dont Python essaie de vous aider.

Maintenant que vous savez comment lire un suivi Python, vous pouvez en apprendre davantage sur certains outils et techniques permettant de diagnostiquer les problèmes signalés par la sortie de votre suivi. Intégré de Python traceback module peut être utilisé pour travailler avec et inspecter les retraits. le traceback module peut être utile lorsque vous avez besoin de tirer davantage de la sortie de traceback. Il serait également utile d’en savoir plus sur certaines techniques de débogage de votre code Python.