Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Lire un code que vous n’avez pas écrit

Après cette leçon: Je peux trouver où vit une fonction dans un code que je n’ai pas écrit et suivre un appel d’un fichier à l’autre.

Leçon de 60 min14 commandesLab Linux du quotidien : la trentaine de commandes que les ingénieurs tapent de tête

Comment trouver où vit une fonction

Une base de code, c’est tout le code d’un même programme. Le premier jour d’un emploi, on vous en confie une que d’autres ont écrite, avec des milliers de lignes et sans plan.

Personne ne lit tout. On apprend à poser une question, à chercher la réponse et à suivre les appels à partir de là.

À la fin de cette leçon

Remarque

Je peux trouver où vit une fonction dans un code que je n’ai pas écrit et suivre un appel d’un fichier à l’autre.

Mots clés

MotCe que ça veut dire
Base de codetous les fichiers de code qui forment un même programme
Point d’entréele fichier ou la fonction où le programme commence
Recherchechercher un mot dans tous les fichiers, avec un outil comme grep
Appelantune ligne de code qui utilise une fonction
Chaîne d’appelsles fonctions auxquelles un appel mène, l’une après l’autre
Test comme documentationun test qui montre, en code, ce qu’une fonction promet

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Partir d’une question, pas d’un fichier

N’ouvrez pas le premier fichier pour lire de haut en bas. Posez une petite question : où calcule-t-on la remise du coupon ?

Regardez d’abord la forme des dossiers. Lancez le programme pour voir ce qu’il fait. Puis cherchez un mot visible à l’écran.

Créez d’abord le projet. Un dossier de cache caché ajouterait du bruit aux recherches : le premier Run le désactive.

Empêcher Python d’écrire des caches

Commande
export PYTHONDONTWRITEBYTECODE=1

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Créer les deux dossiers

Commande
mkdir -p ~/lirecode/boutique ~/lirecode/tests

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Entrer dans le projet

Commande
cd ~/lirecode

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire la liste des prix

Commande
printf 'PRIX = {"the": 250, "tasse": 899, "livre": 1200}\n\n\ndef prix_unitaire(code):\n    return PRIX[code]\n' > boutique/prix.py

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire les coupons

Commande
printf 'COUPONS = {"PROMO10": 10, "MOITIE": 50}\n\n\ndef pourcentage_remise(code):\n    return COUPONS.get(code, 0)\n' > boutique/remises.py

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire le total de la commande

Commande
printf 'from boutique.prix import prix_unitaire\nfrom boutique.remises import pourcentage_remise\n\n\ndef total_commande(articles, coupon=None):\n    total = 0\n    for code, nombre in articles:\n        total = total + prix_unitaire(code) * nombre\n    pourcentage = pourcentage_remise(coupon)\n    return total - total * pourcentage // 100\n' > boutique/commandes.py

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire la commande

Commande
printf 'import sys\nfrom boutique.commandes import total_commande\n\n\ndef main(arguments):\n    articles = [("the", 2), ("tasse", 1)]\n    coupon = arguments[0] if arguments else None\n    print(total_commande(articles, coupon))\n\n\nmain(sys.argv[1:])\n' > boutique/cli.py

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire les tests

Commande
printf 'import unittest\nfrom boutique.commandes import total_commande\n\n\nclass CommandeTest(unittest.TestCase):\n    def test_sans_coupon(self):\n        self.assertEqual(total_commande([("the", 2)]), 500)\n\n    def test_promo10(self):\n        self.assertEqual(total_commande([("the", 2)], "PROMO10"), 450)\n' > tests/test_commandes.py

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Regarder la forme du projet

Commande
ls -R

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Le lancer avec un coupon

Commande
python3 -m boutique.cli PROMO10

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Chercher un mot que vous voyez

Le programme a affiché 1260. Le coupon s’appelait PROMO10, et ce mot est forcément écrit quelque part. grep -rn cherche dans tous les fichiers sous les dossiers nommés, et affiche le fichier, le numéro de ligne et la ligne.

Un nom visible à l’écran est la meilleure porte d’entrée d’un code inconnu.

Chercher le nom du coupon

Commande
grep -rn "PROMO10" boutique tests

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Suivre l’appel jusqu’à l’endroit suivant

La recherche a trouvé une table de coupons dans remises.py. Une table ne fait rien seule : posez la question suivante. Qui l’utilise ?

Cherchez la fonction qui lit la table. Une ligne la définit, une l’importe et une l’appelle. L’appel est l’endroit où la remise atteint la commande.

Trouver chaque usage de la fonction

Commande
grep -rn "pourcentage_remise" boutique

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Exemple travaillé : la chaîne d’appels d’une commande

ÉtapeFichier et fonctionCe qui se passe
1boutique/cli.py, mainLe point d’entrée lit le coupon sur la ligne de commande
2boutique/commandes.py, total_commandeAdditionne les prix, puis demande la remise
3boutique/prix.py, prix_unitaireDonne le prix d’un article
4boutique/remises.py, pourcentage_remiseCherche le coupon, ou donne 0

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Lire les tests : ce que le code promet

Un bon test dit ce qu’une fonction doit faire, avec de vraies entrées et les réponses. C’est la seule documentation qui ne peut pas vieillir, car elle échoue quand elle vieillit.

Listez les noms des tests, puis lancez-les. S’ils passent, ce que vous avez lu est vrai aujourd’hui.

Lister les tests

Commande
grep -n "def test" tests/test_commandes.py

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Lancer les tests

Commande
python3 -m unittest discover -s tests 2>&1 | grep -E "^(OK|FAILED)"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Une erreur fréquente

Attention

Beaucoup lisent chaque fichier depuis le début, en espérant tout comprendre d’abord. Cela prend des jours et la plupart ne concerne pas votre question. Posez une question, cherchez, suivez l’appel, et arrêtez-vous quand vous pouvez répondre.

Pour aller plus loin : un projet plus grand

Choisissez un projet que vous utilisez, avec ses sources sur votre machine. Prenez une chose qu’il fait, comme la lecture d’un fichier de réglages.

Écrivez la question, le mot cherché et la chaîne de fichiers suivie. Combien d’étapes cela a-t-il pris ?

À propos de ce labo et de sa source: Lab Linux du quotidien : la trentaine de commandes que les ingénieurs tapent de tête

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.