2022-08-12 13:31 Temps de lecture : 14 min

Comprendre si __name__ == '__main__' en Python

Ce guide a pour objectif de vous éclairer sur la fonctionnalité et la portée de la condition if __name__ == '__main__' en Python.

Avez-vous déjà exploré des projets Python composés de multiples modules ?

Si tel est le cas, vous avez certainement rencontré la condition if __name__ == '__main__' dans un ou plusieurs de ces modules. Nous allons, dans les prochaines minutes, décrypter le sens de cette condition et examiner un exemple concret de son utilité.

Commençons sans plus tarder !

Quelle est la signification de __name__ en Python ?

En Python, un module est un fichier avec l'extension .py, regroupant des définitions de fonctions, des ensembles d'expressions à évaluer, etc. Par exemple, si nous avons un fichier nommé hello_world.py, on le désigne comme le fichier hello_world.py ou le module hello_world.

Lors de l'exécution d'un module Python, l'interpréteur Python attribue des valeurs à certaines variables spéciales avant de lancer l'exécution ; __name__ est l'une d'elles. Pour bien comprendre la signification de __name__, il est essentiel de saisir le fonctionnement des importations en Python.

📁 Téléchargez le code source de cette section ici.

Dirigez-vous vers le répertoire exemple-1. Vous y trouverez le fichier module1.py. La variable __name__ réside dans l'espace de noms du module en cours.

Ce module affiche une ligne, suivie de la valeur de la variable __name__.

        # example-1/module1.py
        print("Ceci est module1.")
        print(f"La variable __name__ du module 1 est : {__name__}.")
    

Maintenant, exécutons module1 depuis l'invite de commandes.

        $ python module1.py
    

Dans le résultat, nous constatons que la variable __name__ est définie sur __main__.

        Ceci est module1.
        La variable __name__ du module 1 est : __main__.
    

Importation de modules en Python

Au-delà de l'exécution d'un module Python, vous pourriez avoir besoin d'utiliser les fonctionnalités d'un autre module Python à l'intérieur du module actuel. Python facilite cette démarche grâce aux importations.

Les importations vous permettent de réutiliser des fonctionnalités provenant d'un autre module, en l'intégrant dans la portée du module actuel, sans avoir à récrire le code.

Le fichier module2.py contient les éléments suivants. Nous avons importé module1 à l'intérieur de module2.

        # example-1/module2.py
        
        import module1 # module1 est importé
        
        print(f"Ceci est module2")
        print(f"La variable __name__ du module2 est : {__name__}.")
    

Exécutons module2.py et observons le résultat.

        $ python module2.py
    

Dans le résultat ci-dessous :

  • On voit que module1 est exécuté en arrière-plan lorsque nous l'importons dans module2, et que le résultat correspondant est affiché.
  • Cette fois, cependant, la variable __name__ n'est pas __main__, mais module1.
  • Comme nous avons exécuté module2 directement, la variable __name__ correspondant à ce module est maintenant __main__.
        Resultat
        
        Ceci est module1.
        La variable __name__ du module 1 est : module1.
        Ceci est module2
        La variable __name__ du module2 est : __main__.
    

💡 Point clé :

– Si un module est exécuté directement, sa variable __name__ est définie sur __main__.

– Si un module est importé dans un autre module, sa variable __name__ est définie sur le nom du module.

Exemple de if __name__ == '__main__' en Python

Dans cette section, nous allons étudier une application concrète de la condition if __name__ == '__main__'. Nous allons définir une fonction simple, puis élaborer des tests unitaires pour vérifier que la fonction fonctionne comme prévu.

📁 Téléchargez le code source et suivez le guide.

Le code de cette section se trouve dans le dossier exemple-2.

Ici, add.py est un fichier Python qui contient la définition de la fonction add_ab(). La fonction add_ab() accepte deux nombres quelconques et retourne leur somme.

        # example-2/add.py
        
        def add_ab(a,b):
            return a + b
    

Nous utiliserons le module unittest de Python pour tester la fonction add_ab().

Écrire des cas de test pour une fonction Python

Examinez le fragment de code ci-dessous, qui contient le contenu du module test_add.

        # example-2/test_add.py
        
        import unittest
        from add import add_ab
        
        class TestAdd(unittest.TestCase):
            def test_add_23(self):
                self.assertEqual(add_ab(2,3), 5)
            
            def test_add_19(self):
                self.assertEqual(add_ab(1,9), 10)
            
            def test_add_1_minus7(self):
                self.assertEqual(add_ab(1,-7), -6)
    

Le code ci-dessus réalise les opérations suivantes :

  • Importe le module unittest intégré à Python.
  • Importe la fonction add_ab() depuis le module d'addition.
  • Définit la classe de test TestAdd et un ensemble de cas de test sous forme de méthodes au sein de cette classe.

Pour configurer des tests unitaires pour votre code, vous devez d'abord définir une classe de test qui hérite de unittest.TestCase. Chaque cas de test doit être spécifié comme une méthode au sein de la classe, et son nom doit commencer par test_.

Note : Si les méthodes ne sont pas nommées test_, les tests correspondants ne seront pas détectés et ne seront donc pas exécutés.

Essayons maintenant d'exécuter le module test_add depuis le terminal.

        $ python test_add.py
    

Vous remarquerez qu'il n'y a aucun affichage, et qu'aucun des tests n'a été exécuté.

Pourquoi cela ?🤔

C'est parce que pour exécuter les tests unitaires, vous devez exécuter unittest comme module principal lors de l'exécution de test_add.py, en utilisant la commande ci-dessous.

        $ python -m unittest test_add.py
    

Lorsque nous exécutons la commande ci-dessus, nous constatons que les trois tests ont été exécutés avec succès.

        Resultat
        ...
        ----------------------------------------------------------------------
        Ran 3 tests in 0.000s
        
        OK
    

Il serait plus pratique de lancer les tests lorsque ce module test_add est exécuté directement, n'est-ce pas ? Apprenons comment faire dans la section suivante.

Utilisation de if __name__ == '__main__' pour exécuter unittest en tant que module principal

Si vous souhaitez que tous les tests unitaires soient lancés lorsque le module est exécuté directement, vous pouvez ajouter la condition suivante :

        # example-2/test_add.py
        
        import unittest
        from add import add_ab
        
        class TestAdd(unittest.TestCase):
            def test_add_23(self):
                self.assertEqual(add_ab(2,3), 5)
            
            def test_add_19(self):
                self.assertEqual(add_ab(1,9), 10)
            
            def test_add_1_minus7(self):
                self.assertEqual(add_ab(1,-7), -6)
        
        # Exécuter unittest comme module principal
        if __name__ == '__main__':
                unittest.main()
    

La condition dans l'extrait de code ci-dessus indique à l'interpréteur Python : si ce module est exécuté directement, lance le code qui se trouve à l'intérieur, c'est-à-dire unittest.main().

Vous pouvez exécuter le module test_add après avoir ajouté les deux lignes de code ci-dessus.

        $ python test_add.py
    

▶️ L'exécution directe du module de test lance maintenant les trois tests que nous avons définis.

        Resultat
        ...
        ----------------------------------------------------------------------
        Ran 3 tests in 0.000s
        
        OK
    

Le résultat OK ci-dessus indique que tous les tests se sont déroulés avec succès. Les trois points ... signifient que trois tests ont été exécutés et ont tous réussi.

Modifions maintenant la valeur de retour attendue de test_add_1_minus7 en 8. Étant donné que la fonction retourne -6 dans ce cas, un test devrait échouer.

        def test_add_1_minus7(self):
            self.assertEqual(add_ab(1,-7), 8)
    

Comme on le voit dans le résultat ci-dessous, on obtient .F.. Parmi les trois tests, l'un a échoué (le deuxième test). Dans le traçage, nous obtenons une AssertionError indiquant -6 != 8.

        Resultat
        .F.
        ======================================================================
        FAIL: test_add_1_minus7 (__main__.TestAdd)
        ----------------------------------------------------------------------
        Traceback (most recent call last):
          File "test_add.py", line 12, in test_add_1_minus7
            self.assertEqual(add_ab(1,-7), 8)
        AssertionError: -6 != 8
        
        ----------------------------------------------------------------------
        Ran 3 tests in 0.021s
        
        FAILED (failures=1)
    

Il est important de noter que les tests ne s'exécutent pas nécessairement dans l'ordre où ils sont spécifiés dans la classe de test. Dans l'exemple ci-dessus, test_add_1_minus7 est définie comme la troisième méthode de la classe de test, mais le test correspondant a été exécuté en deuxième position.

Récapitulatif

J'espère que ce tutoriel vous a aidé à comprendre le fonctionnement de la condition if __name__ == '__main__' en Python.

Voici un bref rappel des points clés à retenir :

  • L'interpréteur Python définit la variable __name__ avant d'exécuter le script Python.
  • Quand un module est exécuté directement, la valeur de __name__ est __main__.
  • Lorsque vous importez un module dans un autre script Python, la valeur de __name__ correspond au nom du module.
  • Vous pouvez utiliser if __name__ == '__main__' pour contrôler l'exécution et déterminer quelles parties du module doivent être exécutées respectivement lors des exécutions directes et importées.

À présent, je vous invite à consulter ce guide détaillé sur les ensembles en Python. Bon apprentissage !🎉

Auteur
France

Rédacteur tech, guides pratiques et astuces numériques.