- Apprendre
- Informatique et numérique
- Programmation
- Python : variables, boucles, fonctions et fichiers
- Modules et débogage Python
Modules et débogage Python, bases des tests
math et random, écris tes propres modules et installe des paquets depuis PyPI avec pip. Lis ensuite les traces d’appels et les messages d’erreur, trouve les bugs grâce à une démarche de débogage pas à pas et vérifie tes fonctions avec des instructions assert et tes premiers tests unitaires.DébutantUnité 9 sur 10 de la formation Formation : Python : variables, boucles, fonctions et fichiers
Ce que tu vas apprendre
- Importer du code prêt à l’emploi dans un programme avec des instructions import, utiliser des modules de la bibliothèque standard comme
mathetrandom, répartir ton code dans des modules et installer des paquets tiers avec pip.- Importer du code dans un programme avec l’instruction importUtiliser correctement
import,from … importetas, accéder aux noms par notation pointée et distinguer les erreurs d’importation. - Calculer et simuler avec math, random et d’autres modules standardUtiliser les principales fonctions de
mathetrandom, éviter leurs pièges courants et connaître quelques autres modules courants de la bibliothèque standard. - Écrire et importer tes propres modulesRépartir le code dans tes propres fichiers
.py, les importer, éviter les conflits de noms et utiliserif __name__ == "__main__":pour qu’un fichier puisse être à la fois exécuté et importé. - Installer et gérer des paquets avec pipInstaller, examiner, mettre à niveau et supprimer des paquets tiers depuis PyPI, les importer sous le bon nom et résoudre les problèmes d’installation courants.
- Importer du code dans un programme avec l’instruction import
- Utiliser les messages d’erreur de Python pour trouver où et pourquoi un programme a échoué, et distinguer les erreurs de syntaxe, d’exécution et de logique.
- Lire une trace d’appels de bas en hautTrouver le type d’exception, le message, la ligne qui a échoué et la chaîne d’appels qui y a conduit.
- Reconnaître les erreurs courantes et leurs causesRelier les types d’exceptions les plus fréquents à leurs causes et corrections habituelles, et repérer les erreurs de logique qui ne produisent aucun message.
- Lire une trace d’appels de bas en haut
- Localiser la cause d’un bug grâce à une démarche pas à pas au lieu de procéder au hasard, et examiner un programme en cours d’exécution avec des appels à print et un débogueur.
- Suivre une démarche de débogage pas à pasReproduire un bug, formuler et tester une hypothèse, cerner la cause, la corriger et effectuer de nouveaux tests.
- Examiner un programme avec des appels à print, des tableaux de suivi et un débogueurObserver comment les valeurs changent pendant l’exécution du code, en ajoutant des appels à print, en suivant l’exécution à la main ou en mettant le programme en pause à des points d’arrêt.
- Suivre une démarche de débogage pas à pas
- Utiliser
assertpour indiquer ce qui doit être vrai, écrire de petits tests automatisés pour tes fonctions, puis les exécuter et les lire avec le module standardunittest.- Vérifier des hypothèses avec l’instruction assertÉcrire des instructions
assertavec des messages clairs et savoir quand les assertions sont adaptées ou non. - Écrire tes premiers tests unitaires pour tes fonctionsÉcrire des fonctions de test avec des assertions, choisir des cas typiques, des cas aux limites et des cas extrêmes, et utiliser les tests qui échouent pour trouver et corriger les bugs.
- Organiser et exécuter des tests avec unittestÉcrire des tests
unittest.TestCase, les exécuter et lire le rapport des tests réussis, des échecs de test et des erreurs.
- Vérifier des hypothèses avec l’instruction assert
Modules et débogage Python : cours
1Réutiliser des modules et installer des paquets
Le code importé permet à un petit programme d’utiliser des calculs, des simulations et des outils écrits ailleurs. Tu vas choisir une forme d’importation, utiliser des fonctions de la bibliothèque standard et organiser tes propres fonctions pour qu’un autre fichier puisse les réutiliser. L’installation soulève une question distincte : quelle installation de Python reçoit un paquet tiers ? Comprendre ce lien facilite le diagnostic d’un module manquant et permet de garder clairs les noms de chaque programme.
1.1 Importer un module ou des noms choisis
Un module contient du code Python qu’un autre programme peut réutiliser. La plupart des modules sont des fichiers .py. La bibliothèque standard est fournie avec Python ; le code tiers nécessite une installation séparée. Un paquet regroupe des modules apparentés, généralement dans un dossier.
Adapter l’appel à l’importation
Une importation crée des noms dans ton programme. La forme choisie détermine comment tu appelles le code importé.
| Instruction | Nom créé | Exemple d’appel |
|---|---|---|
import math | math | math.sqrt(16) |
from math import sqrt | sqrt | sqrt(16) |
import statistics as stats | stats | stats.mean([2, 4, 9]) |
from random import randint as roll | roll | roll(1, 6) |
La notation pointée permet de rechercher un nom dans un module ou un objet. Dans math.sqrt(16), Python trouve sqrt dans math et l’appelle avec 16. Le résultat est 4.0. La constante math.pi ne nécessite pas de parenthèses d’appel, car c’est une valeur, pas une fonction.
Après import math, sqrt(16) seul lève NameError : le programme possède un nom pour le module, mais aucun nom distinct pour sqrt. Après from math import sqrt seul, l’erreur inverse, math.sqrt(16), lève aussi NameError parce que math n’a pas été lié. Un alias remplace le nom habituel de la liaison importée : import statistics as stats crée stats, pas les deux noms.
Effectuer le même calcul de deux façons
Un triangle rectangle a des côtés de longueurs 3 et 4. Élève d’abord les côtés au carré et additionne-les, puis prends la racine carrée.
import math
length = math.sqrt(3**2 + 4**2)
print(length) # 5.0
L’expression dans l’appel devient 9 + 16, puis 25 ; sqrt renvoie 5.0. Avec from math import sqrt, écris plutôt length = sqrt(3**2 + 4**2). Le préfixe du module rend visible l’origine d’une fonction et évite d’introduire ses autres noms dans l’espace de noms de ton programme. La liaison math elle-même peut toutefois remplacer une variable antérieure appelée math.
Garder des noms clairs
Évite from math import *. Cette importation générique introduit les noms publics dans ton programme sans les nommer individuellement. Par exemple, e = 5 suivi de cette importation fait passer e à 2.718281828459045. Une importation qui semble sans rapport peut donc modifier un calcul ultérieur. PEP 8 recommande les importations explicites et les place en haut du fichier, à raison d’un module par ligne : bibliothèque standard d’abord, paquets tiers ensuite, tes propres modules en dernier.
Python exécute le code de premier niveau d’un module lors de sa première importation pendant l’exécution d’un programme. Les importations suivantes réutilisent le module chargé ; elles ne le relancent pas.
Utiliser l’erreur pour choisir la correction
| Erreur | Ce qu’il faut examiner |
|---|---|
ModuleNotFoundError avec import mathh | L’orthographe et l’installation du module |
ImportError avec from math import square_root | Le nom demandé au module |
AttributeError avec math.sqroot(16) | Le nom après le point |
Dans la console interactive, exécute import math, puis dir(math) pour lister ses noms. Exécute help(math.sqrt) pour lire la documentation d’une fonction. La référence officielle de la bibliothèque Python explique ses arguments et son résultat.
Points clés
import modulecrée une liaison pour le module ; accède à son contenu avec la notation pointée.from module import namecrée la liaison choisie ;aspermet de choisir un alias.- Les importations explicites rendent l’origine des noms claire et réduisent les remplacements accidentels.
- Les erreurs d’importation distinguent un module introuvable, un nom importé indisponible et un attribut manquant.
dir()liste les noms ;help()explique comment en utiliser un.
1.2 Choisir les fonctions de math et random
La bibliothèque standard fournit des outils testés pour les calculs et les simulations. Le choix d’une fonction commence par le résultat recherché : un nombre entier, une mesure arrondie, un élément aléatoire ou une liste réorganisée.
L’arrondi a plusieurs sens
Après import math, math.sqrt(16) renvoie le flottant 4.0. math.pi et math.e fournissent les constantes 3.141592653589793 et 2.718281828459045. math.factorial(5) multiplie les nombres entiers de 1 à 5 et renvoie 120.
| Expression | Résultat | Signification |
|---|---|---|
math.floor(7.9) | 7 | Plus grand entier inférieur ou égal à la valeur |
math.ceil(2.1) | 3 | Plus petit entier supérieur ou égal à la valeur |
math.floor(-2.5) | -3 | L’arrondi inférieur va vers l’infini négatif |
int(-3.5) | -3 | La conversion tronque vers zéro |
round(2.5) | 2 | Une valeur exactement à mi-chemin est arrondie au pair |
round(3.5) | 4 | L’entier pair voisin est 4 |
Pour 23 mètres carrés de mur et 10 mètres carrés par pot de peinture, la division donne 2.3 pots. Pour acheter des pots entiers, il faut utiliser math.ceil(23 / 10), qui renvoie 3. round(2.3) donne 2 et laisse trop peu de peinture.
La fonction native round() ne nécessite aucune importation. Pour un cercle de rayon 2, round(math.pi * 2 ** 2, 2) donne 12.57. L’arrondi modifie la précision d’un nombre ; c’est une opération différente de l’achat d’un nombre suffisant de pots entiers.
Vérifier les domaines de définition et les comparaisons de flottants
math.sqrt(-1) lève ValueError, car cette entrée n’a pas de racine carrée réelle. Les flottants calculés demandent aussi de l’attention : à cause du stockage binaire, 0.1 + 0.2 == 0.3 vaut False. math.isclose(0.1 + 0.2, 0.3) vaut True ; utilise cette fonction pour comparer approximativement des flottants calculés.
Choisir l’opération aléatoire
Le module random utilise un algorithme pour produire des résultats pseudo-aléatoires.
| Appel | Résultat |
|---|---|
random.randint(1, 6) | Un entier de 1 à 6, bornes comprises |
random.randrange(1, 6) | Un entier de 1 à 5 |
random.random() | Un flottant supérieur ou égal à 0,0 et strictement inférieur à 1,0 |
random.uniform(a, b) | Un flottant entre les bornes fournies |
random.choice(items) | Un élément |
random.sample(items, k) | Des éléments à k positions, sans remise |
random.shuffle(items) | Réorganise la liste existante ; renvoie None |
Garde random.shuffle(cards) sur sa propre ligne. Réaffecter son résultat à cards fait perdre la liaison à la liste en la remplaçant par None. Tirer des positions est aussi différent d’exiger des valeurs distinctes : random.sample([1, 1], 2) renvoie [1, 1].
Exécuter une simulation reproductible
import random
sevens = 0
for _ in range(1000):
if random.randint(1, 6) + random.randint(1, 6) == 7:
sevens += 1
print(sevens)
Six des 36 couples équiprobables ont une somme de 7 : le nombre obtenu est donc généralement proche de 167, mais il change d’une exécution à l’autre. Pour reproduire une séquence lors du débogage, appelle random.seed(42) avant de générer les valeurs, avec la même version de Python et la même séquence d’appels. Pour les mots de passe ou les jetons de sécurité, utilise secrets.
Trouver d’autres outils courants
statistics.mean([2, 4, 9]) renvoie 5 ; statistics.median([2, 4, 9]) renvoie 4. datetime.date.today() donne la date du jour. Après import sys, sys.argv contient le nom du script suivi de ses arguments : l’exécution de python greet.py Ada fournit ['greet.py', 'Ada'].
Points clés
floor,ceil,intetroundrépondent à différentes questions d’arrondi.- Utilise
math.isclosepour comparer des flottants calculés. randintinclut les deux bornes ;randrangeexclut sa borne de fin.samplechoisit des positions sans remise : des valeurs identiques dans l’entrée peuvent donc être répétées.shufflemodifie une liste en place et renvoieNone.- Une graine fixe aide à reproduire un comportement aléatoire ; les jetons de sécurité nécessitent
secrets.
1.3 Rendre un fichier réutilisable sans lancer son programme
Une fonction devient plus facile à réutiliser lorsqu’elle se trouve dans un module consacré à une tâche précise. Un autre programme peut importer cette fonction et un test peut la vérifier sans demander à une personne d’exécuter toute l’application.
Séparer la fonction de son appelant
Enregistre ce code sous le nom geometry.py :
"""Calculations for simple shapes."""
import math
def circle_area(radius):
"""Return the area of a circle with the given radius."""
return math.pi * radius ** 2
Dans le même dossier, enregistre cet appelant sous le nom main.py :
import geometry
print(geometry.circle_area(2))
Exécute python main.py. Python trouve geometry, crée sa fonction, puis l’appelant exécute cette fonction. Le résultat affiché est 12.566370614359172. Importe le module sans la terminaison .py. Un nom de module valide utilise des lettres, des chiffres et des tirets bas, avec un premier caractère valide ; my_tools.py fonctionne avec import my_tools, tandis que import my-tools est une syntaxe invalide.
Les chaînes au début du module et de la fonction sont des docstrings. Elles décrivent le rôle du code et apparaissent dans help(geometry) et help(geometry.circle_area).
Comprendre ce que l’importation exécute
Lors de la première importation, Python exécute dans l’ordre les instructions de premier niveau du module. Une instruction def crée une fonction ; elle n’exécute pas son corps. En revanche, un print(circle_area(2)) non protégé à la fin de geometry.py produirait un affichage pendant l’importation.
Cet effet de bord compte lorsqu’un module contient des invites de saisie ou une boucle de programme. Un test qui veut seulement utiliser circle_area ne devrait pas avoir à lancer le programme et à répondre à ses invites.
Protéger le lancement et garder la fonction accessible
Ajoute ceci sous la fonction réutilisable dans geometry.py :
def main():
print(circle_area(2))
if __name__ == "__main__":
main()
Python définit __name__ pour chaque module. Une exécution directe, python geometry.py, lui donne la valeur "__main__", ce qui rend la condition vraie et appelle main(). L’importation de geometry lui donne la valeur "geometry" : Python ignore donc l’appel. Les définitions placées au-dessus de la garde restent disponibles dans les deux cas.
Ne place pas circle_area elle-même dans la garde. Un programme qui importe le module a besoin de cette définition même lorsque la condition de lancement est fausse. La garde contrôle le moment où l’application démarre ; elle n’empêche pas Python de charger le module.
Savoir où Python cherche
Python vérifie les modules intégrés comme sys, puis parcourt dans l’ordre les dossiers de sys.path. Normalement, le dossier du script exécuté vient en premier dans ce chemin, suivi des dossiers de la bibliothèque standard et des paquets installés. Garder tes propres fichiers à côté du script exécuté est une organisation simple pour un projet de débutant. Une importation ordinaire ne peut pas trouver un module situé hors du chemin de recherche.
Cet ordre peut aussi masquer un module de bibliothèque. Si tu enregistres ton programme sous le nom random.py, son instruction import random peut charger ton fichier à la place du module de bibliothèque. Un appel ultérieur à random.randint(1, 6) lève alors AttributeError. Renomme le fichier, par exemple en dice.py ; Python 3.13 et les versions ultérieures peuvent inclure une indication de renommage dans l’erreur.
Un module chargé est réutilisé au cours d’une même exécution. Dans une console interactive, modifier le fichier et l’importer à nouveau conserve la version chargée. Redémarre la console avant de tester tes modifications.
Points clés
- Importe ton propre fichier
.pyen utilisant son nom de module sans l’extension. - Une importation exécute les instructions de premier niveau, tandis que les corps de fonctions attendent d’être appelés.
- Garde les définitions réutilisables hors de la garde
__main__et le lancement du programme à l’intérieur. - Un fichier local peut masquer un module de bibliothèque qui porte le même nom.
- Redémarre une console interactive pour tester à nouveau un module modifié.
1.4 Installer des paquets pour le Python que tu exécutes
Les paquets tiers ajoutent du code qui n’est pas fourni avec Python. PyPI, le Python Package Index accessible sur https://pypi.org, héberge ces projets. pip les télécharge et les installe pour une installation particulière de Python.
Utiliser le terminal, puis Python
Une commande de terminal et une instruction Python ne se saisissent pas au même endroit. L’invite >>> signifie que tu es dans la console interactive Python. Y saisir pip install requests donne SyntaxError ; Python ne peut pas l’interpréter comme une instruction.
Dans ton terminal, exécute :
python -m pip install cowsay
Puis place ceci dans un programme Python :
import cowsay
cowsay.cow("Hello, Ada")
Le programme affiche une vache dessinée avec des caractères à côté d’une bulle contenant le message. L’installation rend le paquet disponible ; l’importation crée la liaison correspondante dans le programme.
Associer pip à ton interpréteur
La forme -m pip demande au Python indiqué d’exécuter son propre pip. Utilise la commande qui lance tes programmes : souvent python3 sur macOS ou Linux, ou py sur Windows.
python3 -m pip install cowsay
python3 game.py
Les deux lignes utilisent la même commande Python. Si une installation réussit mais qu’un script lève encore ModuleNotFoundError, compare le Python utilisé pour l’installation avec celui utilisé pour exécuter le script. Un éditeur peut avoir sélectionné un interpréteur différent de celui de ton terminal. Utilise le pip de l’interpréteur sélectionné avant de modifier l’importation.
Examiner et entretenir une installation
| Commande de terminal | Rôle |
|---|---|
python -m pip list | Lister les paquets installés et leurs versions |
python -m pip show requests | Afficher les détails, dont l’emplacement d’installation |
python -m pip install --upgrade requests | Mettre à jour vers la dernière version disponible |
python -m pip install "requests==2.32.3" | Choisir cette version précise |
python -m pip uninstall requests | Supprimer le paquet |
Une version précise est utile lorsque tu as besoin du comportement propre à cette version. show aide à vérifier quel emplacement pip a réellement modifié.
Vérifier le nom dans la documentation
Le nom de distribution saisi pour pip peut différer du nom d’importation. Installe beautifulsoup4, puis utilise import bs4 ; installe Pillow, puis utilise import PIL. Installer à plusieurs reprises un nom d’importation n’est pas une correction utile lorsque la documentation indique une autre distribution.
La bibliothèque standard de Python, y compris math, random et unittest, est déjà fournie avec Python. Ces modules ne nécessitent pas d’installation avec pip.
Respecter une installation gérée
Certains systèmes d’exploitation et gestionnaires de paquets protègent leur Python avec une erreur externally-managed-environment. Cela signifie qu’une installation directe est bloquée pour préserver la cohérence de l’installation gérée. Utilise un environnement virtuel, avec un Python et un dossier de paquets distincts pour le projet. Ne force pas l’installation avec sudo pip install.
Tout le monde peut publier sur PyPI. Avant l’installation, vérifie l’orthographe exacte et lis la page et la documentation du projet. Des noms ressemblants peuvent être des tentatives de typosquatting. Privilégie les paquets établis et maintenus, et installe ceux dont ton programme a réellement besoin.
Points clés
- Exécute les commandes pip dans un terminal et les importations dans le code Python.
- Utilise
python -m pipavec la même commande d’interpréteur que celle qui exécute le programme. - Vérifie le nom d’importation dans la documentation ; il peut différer du nom d’installation.
- Utilise pip pour examiner, mettre à jour ou supprimer un paquet, ou pour choisir sa version.
- Un Python géré peut nécessiter un environnement virtuel pour le projet.
- Vérifie l’orthographe du nom et la documentation du paquet avant d’installer du code tiers.
2Lire les erreurs et les traces d’appels
Les messages d’erreur de Python indiquent à la fois l’opération qui a échoué et les appels qui y ont conduit. Lire ces indices dans l’ordre aide à trouver un point de départ utile au lieu de modifier la première ligne que tu reconnais. Tu vas remonter une trace d’appels jusqu’à l’entrée en cause, distinguer les types d’exceptions courants et reconnaître le cas plus discret où un programme s’exécute normalement mais produit un résultat incorrect. Le comportement attendu te donne un élément concret à vérifier.
2.1 Remonter une trace d’appels jusqu’à l’entrée incorrecte
Une trace d’appels indique quels appels étaient actifs lorsqu’une exception non gérée a arrêté le programme. Elle fournit à la fois un point de départ pour la lecture et un chemin pour remonter jusqu’à la valeur qui a provoqué l’échec.
Commencer par la dernière ligne
Considère ce programme complet dans scores.py :
def average(values):
return sum(values) / len(values)
def report(scores):
avg = average(scores)
print(f"Average: {avg:.1f}")
report([])
La dernière ligne de son rapport d’erreur est ZeroDivisionError: division by zero. Elle nomme le type d’exception et décrit l’opération qui a échoué. Commence par là, puis remonte jusqu’à l’emplacement du code juste au-dessus.
Voici une trace d’appels simplifiée, sans les marques d’expression :
Traceback (most recent call last):
File "scores.py", line 8, in <module>
report([])
File "scores.py", line 5, in report
avg = average(scores)
File "scores.py", line 2, in average
return sum(values) / len(values)
ZeroDivisionError: division by zero
Lire chaque cadre comme un appel actif
Un cadre d’exécution indique le fichier, le numéro de ligne et la fonction, suivis du code concerné. in <module> désigne le code de premier niveau. L’appel le plus ancien est en haut ; le plus récent est en bas. Lire en partant du bas inverse cet ordre et permet de se demander ce qui a échoué avant de chercher comment l’exécution en est arrivée là.
- La ligne 2 divise par
len(values). Pour que ce diviseur soit nul,valuesdoit être vide. - La ligne 5 appelle
average(scores): examine donc lesscorestransmis parreport. - La ligne 8 fournit
[], la liste vide. Cela explique comment le diviseur nul est arrivé dans le calcul.
La ligne qui échoue et la cause sont liées, mais peuvent se trouver à des endroits différents. Remplacer la division sans décider de ce que doit signifier une liste vide masquerait une question de conception. L’appelant doit soit éviter une liste vide, soit définir le comportement de la fonction pour une entrée vide.
Utiliser les marques sans dépendre de leur forme exacte
Python 3.11 et les versions ultérieures peuvent ajouter les caractères ^ et ~ pour montrer la partie d’une expression qui a échoué. Ils sont utiles lorsqu’une ligne contient plusieurs opérations. Les marques exactes varient selon la version, mais les emplacements des appels et le message d’exception donnent toujours l’ordre de lecture.
Une trace d’appels peut contenir des cadres de la bibliothèque standard ou d’un paquet installé. Trouve le cadre le plus bas dans ton propre code et examine les arguments que tu y as fournis. Un cadre de bibliothèque indique un emplacement ; il ne prouve pas que la bibliothèque contient le bug.
Reconnaître un rapport d’erreur de syntaxe
Une erreur de syntaxe dans le script lancé empêche ce script de s’exécuter. Python indique un fichier, une ligne, une marque et un message sans l’en-tête habituel de trace d’appels. Par exemple, il manque les deux-points à if True ; total = sum([1, 2, 3] laisse une parenthèse ouverte.
L’emplacement marqué est celui où Python a constaté qu’il ne pouvait pas analyser le code. Lorsque cette ligne semble valide, vérifie si un guillemet ou une parenthèse n’a pas été laissé ouvert à la ligne précédente. Il n’y a pas de chaîne d’appels à l’exécution à suivre lorsque le script lancé ne s’est pas exécuté.
Une exécution ordinaire s’arrête à sa première exception non gérée. Corrige ce problème et relance le programme pour faire apparaître les éventuels problèmes ultérieurs.
Points clés
- Lis d’abord le type d’exception et le message, puis le cadre qui a échoué et ses appelants.
- Les cadres vont de l’appel actif le plus ancien en haut au plus récent en bas.
- Remonte le parcours de la valeur incorrecte ; sa source peut précéder l’arrêt.
- Une erreur de syntaxe dans le script lancé est signalée avant son exécution.
2.2 Distinguer un nom, un type, une valeur et un résultat incorrects
Le nom d’une erreur réduit le champ de recherche et son message apporte des précisions sur les valeurs concernées. Un programme peut aussi être incorrect sans lever d’exception : vérifier sa sortie par rapport au résultat attendu reste donc nécessaire pour trouver les erreurs.
Distinguer trois types de problèmes
| Type | Ce qui se passe | Exemple |
|---|---|---|
| Erreur de syntaxe | Python ne peut pas analyser le code | Deux-points manquants après if |
| Erreur d’exécution | L’exécution atteint une opération invalide | Division par zéro |
| Erreur de logique | L’exécution se termine avec un comportement incorrect | Une boucle ignore un prix |
IndentationError est un type de SyntaxError. Le corps d’une fonction doit être indenté ; l’absence d’un bloc indenté arrête le code avant son exécution. Vérifie aussi les guillemets ou parenthèses non fermés et les mots-clés mal orthographiés.
Examiner les noms et les types
Une NameError signifie que le programme ne connaît pas un nom à cet endroit. Dans prnt("hi"), la fonction native voulue est print. Un nom peut aussi être utilisé avant son affectation, ou une importation peut manquer.
Une TypeError signifie qu’une opération a reçu un type inadapté ou qu’un appel a reçu un nombre incorrect d’arguments. "Age: " + 30 mélange une chaîne et un entier. Écris "Age: " + str(30) ou f"Age: {30}". Si area attend w et h, area(3) provoque aussi une TypeError, cette fois à cause d’un argument manquant.
Le message distingue ces causes. Dans can only concatenate str (not "int") to str, Python nomme les types concernés. Après age = input("Age: "), age est du texte. age + 1 échoue ; pour une saisie entière, int(age) + 1 effectue le calcul.
Une ValueError signifie que le type de l’entrée est accepté, mais que sa valeur ne convient pas. int("12.5") reçoit une chaîne, qui est un type d’entrée accepté, mais le texte ne représente pas un nombre entier sous la forme attendue. math.sqrt(-1) est un autre exemple de valeur inadaptée pour un calcul dans les nombres réels.
Vérifier les positions, les clés et les attributs
| Exception | Exemple | Cause |
|---|---|---|
IndexError | [4, 6, 10][3] | Le dernier indice valide est 2 |
KeyError | {"apples": 3}["pears"] | Le dictionnaire ne contient pas "pears" |
ZeroDivisionError | 10 / 0 | Le diviseur est zéro |
AttributeError | math.sqroot(16) | Le module ne contient pas sqroot |
ModuleNotFoundError | import mathh | Aucun module n’est trouvé sous ce nom |
ImportError | from math import square_root | Le module ne contient pas ce nom importé |
Les divisions par zéro échouent aussi avec // et %. L’accès à une position absente d’une liste diffère de l’accès à une clé absente d’un dictionnaire, même si les deux consistent à demander quelque chose qui manque.
Détecter un résultat qui semble plausible
def total_price(prices):
total = 0
for i in range(1, len(prices)):
total += prices[i]
return total
Pour [4, 6, 10], cette fonction renvoie 16 au lieu de 20. Il n’y a aucune exception : les indices 1 et 2 existent, donc chaque opération est autorisée. La boucle commence trop tard et ignore l’indice 0. L’erreur devient visible lorsque tu compares la sortie au total voulu.
Pour une exception inconnue, recherche son type et le message général dans la documentation officielle de Python. Retire tes propres chemins et valeurs d’entrée de la recherche ; ils expliquent rarement la règle générale.
Points clés
- Les erreurs de syntaxe empêchent l’analyse du code ; les erreurs d’exécution surviennent pendant l’exécution ; les erreurs de logique produisent un comportement incorrect.
NameErrorconcerne une liaison ;TypeErrorconcerne un type ou les arguments d’un appel.ValueErrorconcerne une valeur inadaptée fournie dans un type accepté.IndexError,KeyErroretAttributeErrordésignent différents types d’accès.- Comparer la sortie à un résultat attendu peut révéler une erreur de logique sans trace d’appels.
3Trouver la cause d’un bug
Un résultat incorrect est plus facile à examiner lorsque tu peux le reproduire et préciser en quoi il diffère du résultat attendu. Tu vas transformer cette observation en une hypothèse vérifiable, réduire la recherche à un petit morceau de code et examiner les valeurs qui comptent. Les affichages, les tableaux de suivi et les commandes d’un débogueur offrent différents moyens d’observer l’exécution. Après une correction ciblée, vérifier les cas qui fonctionnaient auparavant aide à révéler les comportements touchés par la modification.
3.1 Tester une cause avant de modifier le code
Un bug est une différence entre le comportement prévu et le comportement obtenu. Le débogage permet d’en trouver la cause et de la corriger. Une séance de débogage utile transforme une observation en une explication vérifiable, puis modifie le code à partir des éléments obtenus.
Reproduire l’échec
Note une entrée précise et le résultat qu’elle produit. Pour la fonction de calcul des prix qui commence sa boucle à l’indice 1, utilise [4, 6, 10]. Le total attendu est 20 ; le total obtenu est 16. Ces valeurs concrètes te permettent de vérifier que chaque étape de la recherche concerne toujours le même bug.
La différence est 4, et le résultat obtenu est égal à 6 + 10. Une hypothèse précise est que le premier prix est ignoré. Cette hypothèse prédit un fait que tu peux examiner : la boucle ne passera jamais par l’indice 0.
Suivre six étapes
- Reproduire : trouve une entrée qui montre le bug de façon fiable.
- Indiquer les résultats attendu et obtenu : calcule le résultat attendu indépendamment.
- Formuler une hypothèse : indique une cause possible et le comportement qu’elle prédit.
- La tester : examine les valeurs avec des affichages, un tableau de suivi ou un débogueur.
- Corriger la cause : effectue une modification ciblée.
- Tester à nouveau : exécute le programme avec l’entrée qui échouait et les cas qui fonctionnaient auparavant.
Affiche l’indice dans la boucle. Pour cette entrée, les seuls indices sont 1 et 2, ce qui confirme la prédiction. Faire commencer range à 0 corrige le problème de l’élément ignoré. Parcourir directement les prix évite d’avoir à gérer un indice :
def total_price(prices):
total = 0
for price in prices:
total += price
return total
La fonction corrigée renvoie 20 pour [4, 6, 10], 5 pour [5] et 0 pour []. Le cas à un élément est utile, car la boucle erronée renvoyait auparavant 0 pour ce cas.
Ajouter 4 à chaque réponse corrigerait le total observé, mais laisserait la cause en place. Pour [5], ce correctif renverrait 4 ; le montant manquant dépend de l’entrée. Vérifie si une correction proposée explique tous les éléments observés avant de la conserver.
Réduire une recherche plus vaste
La méthode diviser pour régner consiste à vérifier les valeurs qui alimentent le résultat incorrect à un point intermédiaire de l’exécution. Si une valeur nécessaire est déjà incorrecte, examine le code antérieur qui l’a produite. Si les valeurs nécessaires sont encore correctes, suis leur traitement ultérieur. Recommence dans la partie restante.
Tu peux aussi appeler une fonction isolément ou retirer temporairement le code sans rapport. Un exemple minimal reproductible conserve le code le plus court et la plus petite entrée qui échouent encore. Pour un problème observé d’abord dans des centaines d’enregistrements, trouver un ou deux enregistrements qui le déclenchent facilite chaque vérification.
Vérifier la nature réelle des données
Un 5 affiché peut être la chaîne "5". "5" + "3" produit "53", tandis que l’addition numérique donne 8. Examine type(value) pour vérifier le type. Utilise repr(value) pour révéler les espaces et les caractères de saut de ligne qu’un affichage ordinaire peut masquer, comme dans ' Ada'.
Explique le code à voix haute, ligne par ligne, en précisant notamment ce que chaque boucle parcourt réellement et ce que chaque fonction renvoie. C’est le débogage du canard en plastique : expliquer une étape révèle souvent l’écart entre l’opération voulue et celle qui est écrite.
Corrige une cause à la fois pour pouvoir relier le résultat à la modification. Teste à nouveau les cas qui fonctionnaient auparavant ainsi que celui qui échouait.
Points clés
- Reproduis le bug et note les résultats attendu et obtenu avant toute modification.
- Une hypothèse utile prédit un fait que tu peux examiner.
- Corrige la cause par une modification, puis teste à nouveau les cas qui échouaient et ceux qui fonctionnaient auparavant.
- Utilise un exemple minimal ou des valeurs intermédiaires pour réduire la zone de recherche.
- Vérifie les types et les caractères cachés lorsque les valeurs peuvent induire en erreur.
3.2 Observer les changements de valeurs avec des affichages et un débogueur
La réponse finale d’un programme masque le chemin qui l’a produite. Des affichages temporaires, un tableau de suivi et un débogueur permettent de voir ce chemin et de vérifier une hypothèse précise sur l’endroit où il pose problème.
Afficher une valeur à un moment connu
Identifie les valeurs affichées pour le diagnostic afin que le sens de chaque nombre soit clair. Python 3.8 et les versions ultérieures prennent en charge cette forme de f-string :
print(f"{i=} {total=}")
Pour la boucle de calcul des prix erronée, place-la juste avant total += prices[i]. Avec les prix [4, 6, 10], elle affiche :
i=1 total=0
i=2 total=6
Ce sont les totaux avant chaque addition. Après le premier affichage, la boucle ajoute 6 ; après le second, elle ajoute 10. Un affichage après l’addition montrerait des totaux différents. Détermine quel moment répond à ta question avant d’interpréter la sortie.
Suivre le même code à la main
Un tableau de suivi consigne les variables étape par étape. Pour cette boucle :
Indice i | Prix ajouté | Total avant | Total après |
|---|---|---|---|
| 1 | 6 | 0 | 6 |
| 2 | 10 | 6 | 16 |
Il n’y a aucune itération pour l’indice 0. Suis les valeurs réelles de début et de fin écrites dans le code, même si tu sais déjà ce que la boucle devrait faire. Un tableau aide à distinguer ce que tu attends de ce qui se passe.
Mettre en pause à un point d’arrêt
Un débogueur met un programme en cours d’exécution en pause pour te permettre d’examiner son état courant. Un point d’arrêt marque un endroit où faire une pause. Dans des éditeurs comme Thonny et VS Code, clique à côté d’un numéro de ligne et lance le mode débogage ; dans IDLE, fais un clic droit sur la ligne et choisis Set Breakpoint.
Une fois le programme en pause, choisis une commande de progression selon la question étudiée :
| Commande | Effet |
|---|---|
| Pas à pas principal | Exécuter la ligne courante, y compris une fonction appelée |
| Pas à pas détaillé | Entrer dans une fonction appelée sur cette ligne |
| Sortie de fonction | Terminer cette fonction et mettre en pause après son retour |
| Continuer | Exécuter jusqu’à un autre point d’arrêt ou à la fin du programme |
Si l’appelant transmet des arguments corrects mais reçoit une réponse incorrecte, entre dans la fonction avec le pas à pas détaillé. Si tu as seulement besoin de voir le résultat renvoyé, utilise le pas à pas principal sur son appel. Examine les valeurs avant et après la ligne qui pourrait créer l’erreur.
Utiliser le débogueur textuel de Python
Insère breakpoint() juste avant le code que tu veux examiner. Avec la configuration par défaut du débogueur, l’exécution du programme lance pdb à cet endroit. Saisis ces commandes à son invite (Pdb) :
p totalaffichetotal.nexécute la ligne suivante en pas à pas principal.sentre dans un appel de fonction.cpoursuit l’exécution.qquitte la séance de débogage.
Ce sont des commandes du débogueur, pas des lignes à copier dans ton programme.
Distinguer l’affichage des résultats renvoyés
Une fonction peut afficher le bon nombre tout en renvoyant None parce qu’il lui manque return total. Examine la valeur reçue par l’appelant lorsque l’échec se produit après l’appel de fonction. Voir une sortie correcte dans la fonction ne prouve pas que l’appelant a reçu ce nombre.
Utilise les affichages pour obtenir rapidement des indices sur les itérations d’une boucle et le débogueur pour examiner un moment précis. Après avoir corrigé le bug, supprime les affichages temporaires et les appels à breakpoint() pour que le programme terminé s’exécute normalement.
Points clés
- Identifie les valeurs affichées pour le débogage et note si elles le sont avant ou après une mise à jour.
- Un tableau de suivi montre les changements réels des variables, étape par étape.
- Les points d’arrêt mettent l’exécution en pause ; les commandes de progression contrôlent la quantité de code exécutée ensuite.
breakpoint()ouvre pdb par défaut ;p,n,s,cetqsont des commandes du débogueur.- Examine les valeurs renvoyées lorsqu’une fonction affiche le bon résultat mais que son appelant échoue.
- Supprime les affichages de diagnostic temporaires et les points d’arrêt après la correction.
4Vérifier tes fonctions avec des tests
Les vérifications automatisées permettent de répéter un exemple utile chaque fois qu’une fonction change. Tu vas écrire des assertions avec des résultats attendus clairs, choisir des entrées aux limites d’une règle et empêcher les tests de lancer l’application qu’ils importent. Le framework standard unittest donne ensuite à chaque test un nom et un résultat distinct. La lecture de ses échecs et erreurs relie les tests au débogage : le test reproduit un problème et l’examen en trouve la cause.
4.1 Écrire des vérifications qui échouent lorsqu’une hypothèse est fausse
Une assertion énonce ce qui doit être vrai si ton code fonctionne correctement. Elle peut arrêter un bug près de son origine ou comparer le résultat d’une fonction à la valeur attendue.
Écrire une condition et un message facultatif
assert letter_grade(90) == "A", "90 should be an A"
Python évalue la condition. Si letter_grade(90) renvoie "A", la condition est vraie et l’exécution se poursuit sans affichage. Si elle renvoie "B", Python lève AssertionError avec le message 90 should be an A. La trace d’appels indique la vérification qui a échoué.
Sans le message, assert letter_grade(90) == "A" vérifie tout de même le résultat. La dernière ligne de l’exception contient AssertionError, tandis que la trace d’appels montre l’expression. Un message utile indique quelle attente n’a pas été satisfaite ; il doit t’aider à repérer la règle vérifiée.
Arrêter rapidement une erreur interne
Supposons qu’un calcul interne nécessite une liste non vide :
def average(values):
assert len(values) > 0, "values must not be empty"
return sum(values) / len(values)
Une liste vide déclenche désormais l’assertion avant la division. La vérification documente l’hypothèse interne de la fonction et indique directement quand elle n’est pas respectée. Elle ne donne pas de moyenne à une liste vide et ne décide pas comment une application doit réagir à l’absence de données utilisateur.
Maintenir active la validation des entrées utilisateur
L’option -O de Python supprime les instructions assert. Un programme qui utilise une assertion pour rejeter une entrée externe peut donc se comporter différemment lorsqu’il est optimisé. Vérifie les saisies utilisateur et les autres données externes avec les instructions de contrôle habituelles :
def require_score(score):
if score < 0 or score > 100:
raise ValueError("score must be 0 to 100")
return score
Ici, raise ValueError(...) signale une valeur inadaptée. L’instruction if s’exécute toujours avec -O. Choisis une assertion pour une hypothèse interne au programme et une vérification active pour des données externes qui peuvent être incorrectes.
Éviter une vérification qui ne peut jamais échouer
assert est une instruction, pas une fonction. Écris la condition et le message séparés par une virgule :
assert x > 10, "x too small"
Écrire assert (x > 10, "x too small") crée un tuple à deux éléments. Un tuple non vide est vrai même si son premier élément vaut False : l’assertion réussit donc. Python peut avertir que cette assertion est toujours vraie. Des parenthèses autour de la seule condition, comme dans assert (x > 10), ne créent pas ce tuple ; c’est la virgule dans les parenthèses qui pose problème.
Utilise == pour comparer. assert total = 20 est une syntaxe invalide, car = affecte une valeur.
Comparer les nombres avec la précision voulue
Pour un flottant calculé, vérifie que les valeurs sont proches :
import math
assert math.isclose(0.1 + 0.2, 0.3)
Une comparaison exacte échoue ici, car la somme stockée sous forme de flottant diffère légèrement de 0.3. Un test automatisé simple applique la même idée d’assertion à une fonction : assert total_price([4, 6, 10]) == 20. La valeur attendue vient de la règle de la fonction : la vérification peut donc révéler une implémentation incorrecte.
Points clés
assert condition, messagelèveAssertionErrorlorsque sa condition est fausse.- Les assertions peuvent vérifier des hypothèses internes et les résultats attendus des fonctions.
- Utilise
ifet un message d’erreur ou une exception pour les entrées externes ;-Osupprime les assertions. - Une virgule dans
assert (condition, message)crée un tuple dont la valeur de vérité est vraie. - Utilise
==pour l’égalité etmath.isclosepour comparer des flottants calculés.
4.2 Choisir des tests capables de révéler un bug
Un test unitaire vérifie une petite unité de code, généralement une fonction, avec une entrée choisie et un résultat attendu. Les tests automatisés rendent ces vérifications faciles à répéter après des modifications et aident à détecter les bugs qui réapparaissent dans un comportement auparavant correct.
Partir de la spécification
Supposons qu’une fonction de notation doive renvoyer "A" pour les notes d’au moins 90, "B" pour les notes d’au moins 80 mais inférieures à 90, et "C" en dessous de 80. La première condition erronée est score > 90.
Les tests doivent remplir plusieurs rôles :
- Les cas typiques vérifient des entrées ordinaires à l’intérieur de chaque intervalle, comme 95 et 85.
- Les cas aux limites vérifient les valeurs où une règle change, comme 90 et 89, ou 80 et 79.
- Les cas extrêmes vérifient des entrées comme zéro ou une collection vide lorsque les règles de la fonction les autorisent.
Détermine la réponse attendue à partir de ces règles. Copier la réponse du programme actuel dans un test peut conserver son erreur.
Placer les tests à côté du module
Enregistre les tests dans test_grade.py et la fonction dans grade.py. Le lancement de l’application dans grade.py doit être placé sous sa garde __main__, afin que l’importation de la fonction ne lance pas le programme.
from grade import letter_grade
def test_letter_grade():
assert letter_grade(95) == "A"
assert letter_grade(90) == "A"
assert letter_grade(85) == "B"
Avec la règle erronée, la première assertion réussit. La deuxième échoue parce que 90 n’est pas supérieur à 90 ; l’exécution s’arrête là, avant la troisième assertion de cette fonction. Remplacer la première condition par score >= 90 corrige cette limite. Relance tous les tests pour vérifier le cas concerné et le comportement antérieur.
S’assurer que les tests s’exécutent réellement
Définir une fonction de test ne l’appelle pas. Sans outil d’exécution des tests, ajoute test_letter_grade() à la fin du fichier de test, puis exécute python test_grade.py. Pour utiliser pytest, installe-le avec python -m pip install pytest, puis exécute pytest test_grade.py dans le terminal. Il trouve les fonctions de test et indique leurs résultats. N’ajoute pas d’appels manuels lorsque tu confies leur exécution à un outil de test.
Un test qui se contente d’appeler letter_grade(90) ne comporte aucune comparaison. Il peut se terminer avec succès alors que la réponse renvoyée est incorrecte ; il n’échoue que si l’appel lève une exception inattendue. Une assertion relie l’appel au comportement attendu.
Tester les valeurs renvoyées et les propriétés des résultats aléatoires
Une fonction qui se contente d’afficher un total renvoie None. Une comparaison comme assert print_total([4, 6]) == 10 échoue donc même si l’écran affiche 10. Fais renvoyer sa réponse par la fonction de calcul, puis laisse main gérer l’affichage.
Les résultats aléatoires nécessitent une autre attente. On ne peut pas exiger qu’une fonction simulant un dé sans graine fixée renvoie exactement la même face à chaque appel. Vérifie que chacun des 100 appels renvoie une valeur autorisée de 1 à 6, ou initialise la graine avant une séquence reproductible. Un test des bornes réussi vérifie les bornes pour ces appels ; il ne prouve pas que toutes les faces sont équiprobables.
Lorsqu’un nouveau bug apparaît, ajoute un test qui échoue à cause de ce bug avant de corriger la fonction. Garde ce test de régression pour que les modifications ultérieures vérifient à nouveau le même comportement. Des tests réussis établissent ce qui s’est passé pour les cas testés ; d’autres entrées peuvent encore révéler un autre bug.
Points clés
- Détermine les résultats attendus à partir de la spécification, indépendamment de l’implémentation.
- Teste des entrées ordinaires, les limites des règles et les cas extrêmes pertinents.
- Les fonctions de test doivent être appelées ou exécutées par un outil de test ; leur définition seule n’effectue aucune vérification.
- Les assertions doivent comparer les résultats renvoyés au comportement attendu.
- Teste les propriétés adaptées des résultats aléatoires ou prépare une séquence reproductible.
- Garde un test pour chaque nouveau bug découvert afin d’aider à détecter les régressions.
4.3 Exécuter et interpréter un fichier de test unittest
Python inclut unittest, un framework de test qui découvre les tests, les exécute et indique leurs résultats séparément. Il ne nécessite aucune installation avec pip. Sa structure de classe peut servir de modèle pendant que tu apprends à tester des fonctions.
Écrire des méthodes de test indépendantes
Pour une fonction dans grade.py, place ceci dans test_grade.py :
import unittest
from grade import letter_grade
class TestLetterGrade(unittest.TestCase):
def test_top(self):
self.assertEqual(letter_grade(95), "A")
def test_boundary(self):
self.assertEqual(letter_grade(90), "A")
def test_low(self):
self.assertEqual(letter_grade(50), "C")
if __name__ == "__main__":
unittest.main()
TestLetterGrade hérite des outils de test de unittest.TestCase. Chaque test est une méthode dont le nom commence par test. self désigne l’objet test courant ; garde-le dans la liste des paramètres de chaque méthode et avant les appels aux méthodes d’assertion. Tu peux copier cette structure sans concevoir tes propres classes.
Par défaut, les tests s’exécutent par ordre alphabétique des noms de leurs méthodes : test_boundary vient donc avant test_low et test_top. Fais en sorte que chaque test fournisse ses propres entrées et fonctionne indépendamment des tests précédents.
Choisir une méthode d’assertion
| Méthode | Vérification |
|---|---|
self.assertEqual(actual, expected) | Les valeurs sont égales |
self.assertNotEqual(a, b) | Les valeurs diffèrent |
self.assertTrue(condition) | Une condition est vraie |
self.assertFalse(condition) | Une condition est fausse |
self.assertIn(item, collection) | L’élément appartient à la collection |
self.assertAlmostEqual(a, b) | La différence s’arrondit à zéro à 7 décimales par défaut |
Privilégie assertEqual(a, b) à assertTrue(a == b) pour comparer des valeurs : le rapport d’échec affiche les deux valeurs. Les méthodes de unittest conservent aussi leurs vérifications lorsque Python s’exécute avec -O.
Pour vérifier une exception attendue, encadre l’appel avec assertRaises :
def test_score_too_high(self):
with self.assertRaises(ValueError):
letter_grade(120)
Ce test exige que la règle de la fonction rejette cette note avec ValueError. Un retour sans exception fait échouer cette vérification ; une exception différente d’une exception d’assertion constitue une erreur.
Exécuter les tests et lire le rapport
Exécute python test_grade.py pour lancer son unittest.main() protégé par la garde. Ou exécute python -m unittest pour découvrir les fichiers test*.py du dossier courant. python -m unittest -v affiche les noms des tests individuellement et leurs résultats.
Dans le rapport court, . signifie réussite, F signifie qu’une assertion a échoué et E qu’une autre exception s’est produite. Pour une fonction de notation avec score > 90, les trois tests ci-dessus produisent F... Le rapport d’échec de test_boundary montre 'B' != 'A' : le résultat obtenu est "B", tandis que le résultat attendu est "A". Le récapitulatif indique trois tests et un échec.
Avant de modifier la fonction, vérifie l’attente du test par rapport aux règles de notation. Une attente incorrecte nécessite une correction du test. Si aucun test ne s’exécute, examine les noms des méthodes, la garde d’exécution directe et la commande de lancement. Évite aussi de nommer ton fichier unittest.py, car il masque le module standard.
Points clés
- Place les méthodes
testdans une classe qui hérite deunittest.TestCase. - Utilise
self.assertEqualet les autres méthodes d’assertion pour obtenir des vérifications et des rapports clairs. assertRaisesvérifie une exception attendue ; les comparaisons de flottants peuvent utiliserassertAlmostEqual.- Exécute directement un fichier de test protégé par une garde ou utilise
python -m unittestpour découvrir les tests. - Lis
Fcomme une assertion qui a échoué etEcomme une autre exception. - Vérifie un test qui échoue par rapport à la spécification avant de modifier la fonction.
- Chaque test doit fonctionner indépendamment de l’ordre alphabétique d’exécution.
Modules et débogage Python : exemples
1Construire un programme à partir d’éléments réutilisables
20 étapes
- 1IntroductionPartir de code réutilisable
Un programme peut appeler du code provenant de la bibliothèque standard de Python, d’un autre fichier que tu as écrit ou d’un paquet installé. La première question est de savoir quel nom le programme peut utiliser après l’importation.
Tu vas suivre un calcul depuis son importation jusqu’à sa valeur de retour, puis organiser un module réutilisable et associer l’installation d’un paquet à son interpréteur. Au passage, vérifie si un résultat est une valeur à conserver ou une modification apportée à une liste existante.
- 2ExplicationL’importation détermine le style d’appel
Ces importations rendent la même fonction accessible par des liaisons différentes :
import math print(math.sqrt(16))from math import sqrt print(sqrt(16))Les deux affichent
4.0. La première créemath, donc l’appel utilise un point. La seconde créesqrt, qui n’a donc pas besoin du préfixe du module. Utiliser le mauvais style d’appel lèveNameErrorlorsque ce nom n’a pas été lié. - 3ExempleCalculer l’hypoténuse
Avec
import math, pour un triangle rectangle de côtés 3 et 4, on peut utiliser :length = math.sqrt(3**2 + 4**2)Les carrés sont 9 et 16. Leur somme est 25, et
math.sqrt(25)renvoie5.0. Python évalue l’argument avant d’appeler la fonction.Le préfixe indique aussi au lecteur d’où vient
sqrt. Une importation générique masque cette origine et peut remplacer des noms existants, comme une variable nomméee. - 4DéfiSuivre la liaison de l’alias
Un nouveau script exécute ces lignes. Que se passe-t-il à la dernière ligne et comment corriger le problème ?
import statistics as st print(statistics.mean([4, 8, 12]))---reveal---
Le script lève
NameErrorparce que l’importation liest, passtatistics. Utilisest.mean([4, 8, 12]), qui renvoie8. Un alias choisit la liaison dans ce programme ; il ne crée pas aussi le nom d’origine du module. - 5ExempleArrondir pour obtenir suffisamment de contenants entiers
Un mur de 23 mètres carrés doit être peint. Chaque pot couvre 10 mètres carrés.
import math cans = math.ceil(23 / 10)La division donne
2.3;ceildonne3, soit suffisamment de pots entiers.round(2.3)ne donne que2.Pour les entrées négatives, l’arrondi inférieur va toujours vers l’infini négatif :
math.floor(-2.5)vaut-3, tandis queint(-2.5)tronque vers zéro et donne-2. - 6Point cléAdapter la comparaison au nombre
Les flottants calculés peuvent différer légèrement des valeurs décimales attendues :
0.1 + 0.2 == 0.3 # False math.isclose(0.1 + 0.2, 0.3) # TrueVérifie que les valeurs sont proches pour effectuer cette comparaison approchée. Par ailleurs, les entrées autorisées pour une fonction comptent toujours :
math.sqrt(-1)lèveValueError.La fonction native
roundne nécessite aucune importation. Pour une valeur exactement à mi-chemin, elle choisit l’entier pair voisin :round(2.5)vaut2etround(3.5)vaut4. - 7ExplicationChoisir le résultat aléatoire nécessaire
Après
import random, choisis un appel selon son rôle :randint(1, 6)choisit un entier en incluant 6.randrange(1, 6)choisit un entier en excluant 6.random()donne un flottant de 0,0 inclus à 1,0 exclu.choice(items)choisit un élément.sample(items, k)choisitkpositions sans remise.
Deux positions sélectionnées peuvent contenir la même valeur. Tirer les deux positions de
[1, 1]donne donc des 1 répétés. - 8DéfiConserver la liste mélangée
Quelle valeur
namescontient-il à la fin et comment modifier la dernière ligne pour conserver la liste ?names = ["Mina", "Luis", "Jo"] names = random.shuffle(names)---reveal---
Il contient
None.shufflemodifie la liste existante, puis renvoieNone; l’affectation remplace la liaison à la liste par cette valeur de retour. Utiliserandom.shuffle(names)sur sa propre ligne. Le nouvel ordre de la liste est aléatoire, mais la valeur renvoyée est toujours la même. - 9LienRépéter une simulation et trouver d’autres outils
Appelle
random.seed(42)avant de générer des valeurs pour répéter la même séquence avec la même version de Python. Cela facilite la reproduction d’un échec aléatoire. Utilisesecretspour les jetons de sécurité.D’autres modules standard accomplissent des tâches courantes :
statistics.mean([2, 4, 9])donne5, etmediandonne4.datetime.date.today()donne la date du jour.sys.argvliste le nom du script exécuté suivi de ses arguments de ligne de commande. - 10ExemplePlacer une fonction réutilisable dans un module
Enregistre ceci sous le nom
geometry.py:import math def circle_area(radius): """Return the circle's area.""" return math.pi * radius ** 2Un script situé dans le même dossier peut exécuter
import geometry, puisprint(geometry.circle_area(2)). Il affiche12.566370614359172.Importe le fichier sans
.py. La première chaîne de la fonction est sa docstring, quehelp(geometry.circle_area)peut afficher. - 11ExplicationUne importation exécute les instructions de premier niveau
Supposons que
geometry.pyse termine parprint(circle_area(2)), hors d’une fonction. Sa première importation affiche l’aire comme effet de bord.Python exécute dans l’ordre les instructions de premier niveau du module. Définir
circle_areacrée la fonction sans exécuter son corps ; l’appeler dans l’affichage de premier niveau exécute le calcul. Une deuxième importation dans le même processus réutilise le module chargé. Une console interactive conserve aussi cette version chargée après la modification du fichier, jusqu’à son redémarrage. - 12ExempleLancer uniquement lors d’une exécution directe
Laisse la fonction réutilisable au-dessus de ce bloc :
def main(): print(circle_area(2)) if __name__ == "__main__": main()Une exécution directe donne à
__name__la valeur"__main__", doncmain()s’exécute. Une importation lui donne la valeur"geometry", donc le lancement est ignoré.Les définitions restent disponibles dans les deux cas. Un test peut ainsi importer
circle_areasans produire la sortie habituelle du programme. - 13DéfiGarder la fonction accessible au programme qui l’importe
Un fichier définit
convertdans son blocif __name__ == "__main__":. Un nouveau processus de test importe le fichier et ne trouve pasconvert. Quelle organisation permet à la fois la réutilisation et le lancement lors d’une exécution directe ?---reveal---
Déplace
def convert(...)hors de la garde et ne garde que le lancement du programme à l’intérieur. Lors de l’importation, la garde est fausse : une définition placée à l’intérieur est donc ignorée. Déplacer la définition la rend accessible sans lancer l’application. - 14ConseilVérifier le fichier trouvé par une importation
Python vérifie les modules intégrés, puis parcourt
sys.pathdans l’ordre. Le dossier du script apparaît normalement avant les dossiers de bibliothèque. Un fichier localrandom.pypeut donc masquer le modulerandomque tu voulais importer.Renomme ce fichier, par exemple en
dice.py. Pour tes propres fonctions auxiliaires, utilise des noms valides commemy_tools.pyet garde les fichiers à côté du script de débutant qui les importe. Une importation ordinaire ne trouve pas un fichier situé hors du chemin de recherche. - 15ExempleInstaller dans le terminal, importer dans Python
Dans le terminal, exécute :
python -m pip install cowsayLe code Python peut ensuite utiliser :
import cowsay cowsay.cow("Hello, Ada")Le paquet affiche une vache dessinée avec des caractères et une bulle.
pipinstalle le code, tandis queimportcrée la liaison utilisée par ton programme. La commande d’installation n’est pas une instruction Python ; à l’invite>>>, elle produit une erreur de syntaxe. - 16ExplicationUtiliser le pip associé au Python qui exécute le programme
Si un script s’exécute avec
python3, effectue l’installation avec la même commande :python3 -m pip install cowsay python3 game.py-m pipsélectionne le pip associé à cet interpréteur. Sous Windows, ta commande peut êtrepy.Si l’éditeur ne peut pas importer un paquet pourtant installé, compare l’interpréteur qu’il a sélectionné avec celui utilisé dans le terminal. Une installation réussie dans un Python n’installe pas le paquet dans tous les autres.
- 17DéfiDistinguer le nom d’installation du nom d’importation
La documentation d’un paquet indique d’installer
Pillowet d’importerPIL. L’installation réussit pour le Python que tu utilises, maisimport Pillowéchoue. Que faut-il changer et pourquoi ?---reveal---
Utilise
import PIL. Le nom de distribution utilisé par pip peut différer du nom d’importation Python qu’il fournit. Puisque la correspondance entre les interpréteurs est déjà établie, répéter la même commande d’installation laisserait cette erreur de nom en place. - 18ConseilExaminer un paquet avant de le modifier
python -m pip listaffiche les versions installées.show requestsdonne la version et l’emplacement d’un paquet ;install --upgrade requestsle met à jour etuninstall requestsle supprime. Chaque commande courte suitpython -m pip.Vérifie le nom exact sur PyPI et la documentation du projet avant l’installation. En cas d’erreur
externally-managed-environment, utilise un environnement virtuel pour le projet ; ne force pas l’installation avecsudo pip install. - 19DéfiPrévoir une importation et un appel ultérieur
Un nouveau module
sizes.pycontient ce code. Un autre script exécutefrom sizes import batches, puisprint(batches(17)). Qu’est-ce qui s’affiche ?import math def batches(n): return math.ceil(n / 5) if __name__ == "__main__": print(batches(12))---reveal---
Seul
4s’affiche. L’importation crée la fonction mais ignore l’affichage protégé par la garde. L’appel ultérieur divise 17 par 5, puis arrondit 3,4 à l’entier supérieur, soit 4. La liaisonmathdanssizesest accessible à sa fonction. - 20RécapitulatifSuivre le code depuis sa source jusqu’à l’appel
Choisis une importation qui correspond aux noms que tu veux utiliser. Vérifie ce que renvoie un appel de bibliothèque, notamment un éventuel
Nonepour une opération qui modifie une liste.Garde les définitions réutilisables accessibles pendant l’importation et place le lancement de l’application derrière la garde du programme principal. Pour le code installé, associe pip à l’interpréteur qui exécute le programme et vérifie le nom d’importation indiqué dans la documentation. Lorsqu’un appel échoue, ces détails aident à distinguer une liaison manquante, un attribut manquant et une installation manquante.
2Remonter d’un échec à sa cause
11 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionUtiliser le rapport comme indice
- 2ExempleUne liste vide arrive à une division
- 3ExplicationTrouver le cadre le plus récent
- 4ExempleRemonter le parcours de l’argument à travers ses appelants
- 5DéfiLocaliser un argument inadapté
- 6ExplicationDistinguer grammaire, types et valeurs
- 7ExplicationDes accès différents produisent des erreurs différentes
- 8ExempleUn calcul peut se terminer normalement avec un total incorrect
- 9DéfiExpliquer l’échec d’une addition
- 10DéfiUtiliser un cadre de bibliothèque sans mettre en cause la bibliothèque
- 11RécapitulatifChoisir le prochain endroit à examiner
3Examiner un bug, des indices à la correction
14 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionReproduire le résultat incorrect
- 2ExempleIndiquer les résultats attendu et obtenu
- 3ExplicationRendre l’hypothèse vérifiable
- 4ExempleAfficher avant la mise à jour
- 5ExempleSuivre les additions à la main
- 6DéfiInterpréter un affichage après la mise à jour
- 7ExempleCorriger le parcours lui-même
- 8LienTester à nouveau des entrées de formes différentes
- 9ConseilRéduire un échec plus complexe
- 10DéfiVérifier une valeur qui ressemble à un nombre
- 11ExplicationMettre en pause à l’appel à examiner
- 12DéfiChoisir la commande de progression
- 13DéfiExaminer un affichage correct et une valeur de retour incorrecte
- 14RécapitulatifRelier la correction aux indices
4Transformer un bug de limite en test durable
16 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionVérifier le comportement attendu de façon reproductible
- 2ExplicationUne assertion énonce une attente
- 3DéfiTrouver une vérification qui ne peut pas échouer
- 4Point cléMaintenir actives les vérifications des entrées externes
- 5ExempleChoisir des entrées autour du changement de note
- 6ExempleÉcrire une fonction de test qui importe le code
- 7ConseilExécuter les vérifications définies
- 8DéfiCorriger un seuil et conserver la vérification
- 9LienTester le résultat renvoyé ou une propriété valide
- 10ExempleUtiliser le modèle de classe unittest
- 11ExplicationChoisir l’assertion adaptée au résultat
- 12ExempleLire une vérification de note qui a échoué
- 13DéfiDistinguer un échec de test d’une erreur
- 14ConseilVérifier ce que la découverte des tests a réellement exécuté
- 15DéfiUtiliser un rapport pour préparer la correction
- 16RécapitulatifConserver un test pour le comportement corrigé
Modules et débogage Python : QCM
Série 1 : Modules, choix de débogage et résultats des tests10 Questions Pratiques
Question 1 sur 10
import statistics as st, la ligne suivante est statistics.mean([3, 7]). Il n’y a aucune autre importation ni affectation. Qu’est-ce qui explique l’erreur ?Afficher la réponseMasquer la réponse
st dans ce script. Elle ne lie pas aussi statistics : le nom d’origine du module, utilisé seul, lève donc NameError. mean([3, 7]) seul échouerait aussi, car importer un module sous un alias n’importe pas directement les noms de ses fonctions.Question 2 sur 10
Quelle est la valeur de tickets après ce code ?
import random
tickets = [11, 22, 33]
tickets = random.shuffle(tickets)
Afficher la réponseMasquer la réponse
shuffle réorganise la liste existante, puis renvoie None. L’affectation remplace la liaison de tickets par cette valeur de retour : le nom ne désigne donc plus la liste. Pour garder la liaison, appelle random.shuffle(tickets) sur sa propre ligne au lieu d’affecter le résultat.Question 3 sur 10
double, puis contient la ligne non protégée print(double(6)). Un autre script l’importe deux fois au cours d’une exécution. Combien de fois cette ligne produit-elle un affichage ?Afficher la réponseMasquer la réponse
Question 4 sur 10
python -m pip show cowsay indique un emplacement dans Python B, et l’éditeur ne peut pas importer cowsay. Que dois-tu faire en premier ?Afficher la réponseMasquer la réponse
Question 5 sur 10
Afficher la réponseMasquer la réponse
Question 6 sur 10
Cette fonction doit additionner toutes les quantités. Quel type de problème explique le résultat de total([2, 5, 8]) ?
def total(values):
result = 0
for i in range(1, len(values)):
result += values[i]
return result
Afficher la réponseMasquer la réponse
Question 7 sur 10
Afficher la réponseMasquer la réponse
Question 8 sur 10
assert (score >= 0, "negative score"). Elle réussit lorsque score vaut -3. Quelle modification corrige la vérification tout en gardant la validation active avec -O ?Afficher la réponseMasquer la réponse
-O la supprimerait tout de même. Un if qui lève ValueError vérifie l’entrée externe aussi bien en exécution normale qu’en exécution optimisée.Question 9 sur 10
test_discount, qui contient deux assertions, mais ne l’appelle jamais. Tu exécutes ce fichier avec python test_discount.py ; il ne contient aucun code d’exécution des tests. Pourquoi aucune assertion n’est-elle vérifiée ?Afficher la réponseMasquer la réponse
test_discount() dans un fichier exécuté directement ou laisse un outil de test la découvrir. Python ne supprime pas les assertions simplement parce que le nom du fichier commence par test_ ; le problème est ici l’absence d’exécution.Question 10 sur 10
self.assertEqual(lookup("x"), 7). L’appel à lookup lève une KeyError inattendue avant de renvoyer une valeur. Quel symbole marque le résultat de ce test ?Afficher la réponseMasquer la réponse
KeyError inattendue empêche l’assertion d’égalité de comparer les valeurs renvoyées : unittest enregistre donc une erreur, indiquée par E. Une assertion d’égalité fausse produirait F. Le simple fait de ne pas atteindre une comparaison ne fait pas réussir un test lorsqu’une exception inattendue se produit.Série 2 : Importations, indices d’erreur et premières vérifications10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
import math avant son calcul. Comment doit-il appeler la fonction racine carrée sur 81 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
math.ceil(35 / 8) et que représente ce résultat ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
text_tools.py définit shorten. Comment un autre fichier du même dossier peut-il l’importer et l’appeler ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
>>> et tu saisis pip install cowsay. Pourquoi Python signale-t-il une syntaxe invalide ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
ZeroDivisionError. Ses cadres montrent, de haut en bas, show([]), mean(data) et sum(values) / len(values). Quel enchaînement explique le mieux l’échec ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
int("7.25") lève-t-il ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
[9, 2, 5], mais elle renvoie 7. Tu soupçonnes qu’elle ignore le premier élément. Quelle observation permettrait de tester cette idée le plus directement ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Quelles sont les deux lignes affichées ?
total = 0
for n in [3, 8]:
print(f"{n=} {total=}")
total += n
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Que se passe-t-il lorsque ce code s’exécute normalement ?
count = 6
assert count < 5, "too many"
print("saved")
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
La règle prévoit la gratuité jusqu’à un poids de 12 inclus, des frais de 4 de 13 à 18 inclus, et des frais de 7 au-dessus de 18. Les tests pour 5 et 20 réussissent. Quels résultats et quelle modification permettent de diagnostiquer correctement ce code ?
def fee(weight):
if weight < 12:
return 0
if weight <= 18:
return 4
return 7
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 3 : Suivre les causes à travers les modules et les tests10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Qu’affiche ce code ?
from math import sqrt as root
sqrt = 4
result = root(sqrt ** 2)
print(result, sqrt)
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
random.sample(["blue", "blue", "red"], 2). Pourquoi le résultat peut-il contenir deux valeurs "blue" ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Un module contient ce code. Un nouveau processus l’importe, puis appelle helper.answer(). Que se passe-t-il ?
# helper.py
if __name__ == "__main__":
def answer():
return 42
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
run_report(), puis ton appel parse(raw), et se termine dans une conversion de bibliothèque avec ValueError. Tu examines raw à ton appel de parse et trouves "9x", alors que la règle exige un texte représentant un entier. Où poursuivre l’examen ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
result + 2, où result est la valeur renvoyée par l’appel. Pourquoi une TypeError se produit-elle ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
answer = calculate(7). Tu veux examiner la première ligne à l’intérieur de calculate. Quelle commande dois-tu utiliser ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
charge(6) renvoie 3, mais son test attend 3 et réussit. Quelle modification crée un test de régression utile et corrige la règle ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
test_alpha, qui attend 4 mais reçoit 5, test_beta, qui réussit, et test_gamma, qui lève une TypeError inattendue. Quelle chaîne compacte de progression l’exécution alphabétique par défaut produit-elle ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
unittest.TestCase contient check_empty, avec une vérification d’égalité qui échoue, et test_full, avec une vérification qui réussit. L’outil d’exécution indique un test et OK. Comment faire exécuter la vérification de comportement manquante ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 4 : Combiner les décisions d’importation, de débogage et de test10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
random.randint(2, 5) 50 fois. Un nouveau test initialise la graine à la même valeur avec la même version de Python et répète les mêmes appels. Que doivent attendre ses vérifications ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
beautifulsoup4 comme distribution et bs4 comme module. Un script importe bs4 avec succès. Un collègue veut modifier python -m pip install beautifulsoup4 pour installer bs4 afin que les noms correspondent. Cette correspondance est-elle une raison valable de faire ce changement ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
display.py indique ces appels, de haut en bas : start(" "), read_count(text), puis int(text), et se termine par ValueError. Quelle suite d’actions permet le mieux de tester la cause probable avant une correction ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
[6, 3, 2]. Quels résultats attendus et obtenus pour deux nouvelles entrées révèlent le problème restant ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Cette fonction affiche un produit correct, mais son appelant reçoit une TypeError dans area(4, 5) + 1. Où dois-tu examiner l’exécution et quel résultat explique l’échec ?
def area(w, h):
product = w * h
print(product)
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Que se passe-t-il lors d’une exécution ordinaire, sans optimisation ?
import math
assert math.isclose(0.1 + 0.2, 0.3)
assert 0.1 + 0.2 == 0.3
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
pick() renvoie un entier aléatoire de 3 à 7, bornes comprises. pair_total() additionne les résultats de deux appels à pick(). Un test qui affirme que chaque total obtenu sans graine fixée vaut 10 échoue parfois alors que les deux fonctions fonctionnent correctement. Quelle vérification de chaque résultat correspond à l’intervalle requis pour le total ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
reserve(n) doit accepter les nombres entiers de 0 à 8 inclus et lever ValueError hors de cet intervalle. Des tests utilisant assertRaises(ValueError) indiquent F pour -1 parce qu’aucune exception ne se produit, et E pour 9 parce qu’une TypeError se produit. Un test à 2 réussit. Quel comportement la correction doit-elle assurer ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
random.py et importe random, puis échoue parce que random.randint est absent. Quelle première modification traite le conflit de noms ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
assert total == 10 pour un calcul interne et assert age >= 0 pour une saisie utilisateur. Il s’exécute avec -O, avec total égal à 9 et age égal à -1. Qu’arrive-t-il à ces vérifications et quelle modification maintient la validation requise de la saisie ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Tu bloques sur ton propre exercice ? Aide aux Devoirs
Mots-Clés
A
Alias
as pour un module ou un objet importé ; l’importation lie ce nom dans le programme qui importe.stats dans import statistics as stats permet au script d’appeler stats.mean([1, 3, 8]).Assertion
AssertionError si elle est fausse.assert count == 3 compare un résultat interne au nombre attendu que tu as déterminé indépendamment.AssertionError
"wrong total" attire l’attention sur le test qui a comparé le total calculé.B
Bibliothèque standard
math pour les calculs et random pour les simulations, comme les lancers de dés.Bug
C
Cadre d’exécution
Cas extrême
Cas limite
Chaîne d’appels
report à une fonction average montre comment une liste est parvenue à la fonction qui a divisé par sa longueur.Chemin de recherche des modules
sys.path que Python examine après ses modules intégrés lorsqu’il recherche des importations.ModuleNotFoundError lorsque le script l’importe.Code de premier niveau
print peut produire un affichage pendant l’importation même lorsque le programme qui importe n’appelle aucune fonction.D
Débogage
Débogage par affichage
print(f"{i=} {total=}") identifie l’indice de boucle et le total au moment examiné.Débogueur
calculate pour examiner ses arguments lorsque l’appelant reçoit une réponse incorrecte.Découverte des tests
test*.py par défaut de unittest.python -m unittest peut exécuter les fichiers correspondants sans les lister individuellement dans une commande.Distribution
beautifulsoup4 s’installe sous ce nom, mais sa documentation indique aux utilisateurs Python d’importer bs4.Diviser pour régner
Docstring
help().circle_area peut expliquer l’argument du rayon et l’aire renvoyée à l’appelant.E
Erreur d’exécution
Erreur de logique
Erreur de syntaxe
if ready peut être corrigée en ajoutant les deux-points requis avant son bloc indenté.Erreur de test
E peut se produire lorsqu’une fonction lève TypeError avant que la vérification d’égalité reçoive une valeur.Exception
average avant que son appelant affiche la moyenne calculée.Exemple minimal reproductible
É
Échec de test
F peut montrer que la fonction a renvoyé "B" là où la règle vérifiée exigeait "A".G
Garde du programme principal
if __name__ == "__main__": dont le corps s’exécute lors d’une exécution directe et est ignoré lors d’une importation ordinaire.main() permet aux tests d’importer les fonctions du module sans lancer son application.Graine
H
Hypothèse
I
Importation générique
* pour introduire les noms publics d’un module dans le programme courant, ce qui peut masquer leurs origines et remplacer des liaisons existantes.from math import * peut remplacer une variable appelée e par la constante mathématique.ImportError
from demande un nom indisponible dans un module, même si Python a trouvé le module lui-même.from math import square_root indique un problème avec le nom demandé, pas une installation absente.IndexError
names[4] invite à vérifier la longueur de la liste et les bornes de la boucle qui a produit 4.Interpréteur
K
KeyError
"price" peut révéler que le dictionnaire courant n’a jamais reçu l’entrée de prix attendue.M
Masquage de module
random.py peut priver un script de la fonction randint de la bibliothèque.Méthode de test
test, ce qui permet à unittest de découvrir et d’exécuter ses vérifications.test_limit peut vérifier une limite séparément du test d’une entrée ordinaire.Module
.py, dont les fonctions et les variables peuvent être importées pour être utilisées dans un autre programme.math fournit sqrt : un programme peut donc calculer des racines carrées sans définir cette fonction.N
NameError
sqrt après le seul import math signifie que la fonction nécessite ici le préfixe math..Nombre pseudo-aléatoire
random.randint(1, 6) peut représenter le résultat d’un dé dans la simulation d’un jeu de société.Notation pointée
math.sqrt(25) trouve la fonction sqrt dans le module math déjà importé.O
Opération en place
random.shuffle(cards) modifie cards et renvoie None : elle ne nécessite donc pas d’affectation.Option d’optimisation
-O modifie l’exécution de Python en supprimant les instructions assert : une validation requise ne peut donc pas reposer sur ces instructions.P
Paquet
Partie entière
math.floor va vers l’infini négatif lorsque c’est nécessaire.math.floor(-3.2) diffère donc de la conversion avec int(-3.2).Partie entière supérieure
math.ceil effectue cet arrondi à l’entier supérieur.Pas à pas détaillé
result = convert(text) lorsque la valeur renvoyée est incorrecte et que le texte d’entrée semble correct.Pas à pas principal
pip
python3 -m pip show cowsay demande au pip associé à python3 d’afficher les détails d’installation de ce paquet.Point d’arrêt
PyPI
R
Régression
S
Spécification
T
Tableau de suivi
Test unitaire
TestCase
unittest.TestCase peut appeler self.assertEqual dans ses méthodes de test nommées.Tirage sans remise
["A", "A", "B"] peut sélectionner les deux positions qui contiennent "A".Trace d’appels
TypeError
"Score: " + 8 indique qu’une chaîne et un entier ne peuvent pas être assemblés par cette expression.Typosquatting
V
Validation des entrées
if score < 0 reste active lorsque Python s’exécute sans les assertions.ValueError
int("6.2") signifie que la chaîne ne décrit pas un entier sous la forme requise.À propos de cette unité
Crée ton propre Matériel d'Étude
Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.