Définition de __name__ en Python
En Python, __name__ est une variable spéciale intégrée (aussi appelée dunder attribute, pour "double underscore") qui est automatiquement définie par l'interpréteur Python dans chaque module. Sa valeur dépend du contexte d'exécution du fichier :
- Si le fichier est exécuté directement (comme script principal),
__name__vaut la chaîne"__main__". - Si le fichier est importé en tant que module depuis un autre fichier,
__name__vaut le nom du module (c'est-à-dire le nom du fichier sans l'extension.py).
Cette variable est au cœur de l'une des conventions les plus importantes de Python : le fameux bloc if __name__ == "__main__". Si vous suivez notre formation complète sur Python, vous découvrirez que cette notion est essentielle pour écrire du code professionnel et réutilisable.
__name__ fait partie des attributs spéciaux de Python (comme __doc__, __file__, __package__). On les appelle dunder attributes car ils sont entourés de doubles underscores (double underscores → dunder).
Comment fonctionne __name__ ?
Pour bien comprendre __name__, il faut visualiser ce qui se passe lorsque Python exécute un fichier. L'interpréteur attribue automatiquement des métadonnées à chaque module chargé, et __name__ en fait partie.
Exécution directe d'un script
Lorsque vous lancez un fichier Python directement depuis la ligne de commande (par exemple python mon_script.py), l'interpréteur définit __name__ à "__main__" pour ce fichier :
# fichier : mon_script.py
print(__name__)
Résultat en exécutant python mon_script.py :
__main__
Importation en tant que module
Maintenant, si vous importez ce même fichier depuis un autre script, la valeur de __name__ change :
# fichier : autre_script.py
import mon_script
Résultat en exécutant python autre_script.py :
mon_script
Comme vous pouvez le constater, __name__ vaut désormais "mon_script" (le nom du fichier sans .py) et non plus "__main__". C'est cette distinction qui rend __name__ si puissant.
Le bloc if __name__ == "__main__"
La construction if __name__ == "__main__" est probablement le pattern le plus courant en Python. Vous le retrouverez dans la quasi-totalité des projets professionnels. Son rôle est simple : exécuter un bloc de code uniquement quand le fichier est lancé directement, et pas quand il est importé.
Exemple fondamental
# fichier : calculatrice.py
def additionner(a, b):
return a + b
def soustraire(a, b):
return a - b
def multiplier(a, b):
return a * b
if __name__ == "__main__":
# Ce bloc ne s'exécute que si le fichier est lancé directement
print("Test de la calculatrice")
print(f"3 + 5 = {additionner(3, 5)}")
print(f"10 - 4 = {soustraire(10, 4)}")
print(f"6 * 7 = {multiplier(6, 7)}")
Lorsque vous exécutez python calculatrice.py, vous obtenez :
Test de la calculatrice
3 + 5 = 8
10 - 4 = 6
6 * 7 = 42
Mais si vous importez ce module depuis un autre fichier :
# fichier : application.py
import calculatrice
resultat = calculatrice.additionner(100, 200)
print(resultat) # 300
Seul 300 s'affiche. Le bloc de test de la calculatrice ne s'exécute pas, car __name__ vaut "calculatrice" et non "__main__".
Pourquoi est-ce si important ?
Sans cette garde, chaque importation déclencherait l'exécution de tout le code « libre » du module. Imaginez un module qui lance un serveur web ou effectue des calculs lourds : vous ne voudriez pas que cela se produise à chaque import. Le bloc if __name__ == "__main__" vous donne le contrôle total sur ce qui s'exécute et quand.
Exemples pratiques avancés
Structurer un projet avec __name__
Dans un projet bien structuré, chaque module peut être à la fois une bibliothèque de fonctions et un script exécutable. Voici un exemple plus complet :
# fichier : utils.py
def formater_nom(prenom, nom):
"""Formate un nom complet en capitalisant correctement."""
return f"{prenom.capitalize()} {nom.upper()}"
def valider_email(email):
"""Vérifie basiquement qu'un email contient un @."""
return "@" in email and "." in email
def generer_identifiant(prenom, nom):
"""Génère un identifiant unique basé sur le nom."""
return f"{prenom.lower()}.{nom.lower()}"
if __name__ == "__main__":
# Tests manuels rapides
print("=== Tests du module utils ===")
nom_formate = formater_nom("jean", "dupont")
print(f"Nom formaté : {nom_formate}")
email_valide = valider_email("jean@example.com")
print(f"Email valide : {email_valide}")
identifiant = generer_identifiant("Jean", "Dupont")
print(f"Identifiant : {identifiant}")
Vous pouvez ainsi tester rapidement votre module avec python utils.py, tout en l'important proprement ailleurs avec import utils.
Utilisation avec une fonction main()
Une convention très répandue consiste à définir une fonction def nommée main() et à l'appeler dans le bloc de garde. Cela rend le code plus propre et plus testable :
# fichier : app.py
import sys
def traiter_donnees(fichier):
"""Traite les données d'un fichier."""
print(f"Traitement de {fichier}...")
# Logique de traitement ici
return True
def afficher_aide():
"""Affiche l'aide du programme."""
print("Usage : python app.py ")
print("Options :")
print(" -h, --help Afficher cette aide")
def main():
"""Point d'entrée principal du programme."""
if len(sys.argv) < 2:
afficher_aide()
sys.exit(1)
fichier = sys.argv[1]
if fichier in ("-h", "--help"):
afficher_aide()
else:
succes = traiter_donnees(fichier)
if succes:
print("Traitement terminé avec succès !")
if __name__ == "__main__":
main()
Cette approche est recommandée car elle permet de réutiliser la logique de main() dans des tests unitaires sans avoir à exécuter le script entier.
__name__ dans les classes et les fonctions
Il est important de noter que __name__ existe aussi comme attribut des class et des fonctions :
class Vehicule:
pass
def accelerer():
pass
print(Vehicule.__name__) # Vehicule
print(accelerer.__name__) # accelerer
# Utile pour le débogage et la journalisation
def log_appel(func):
def wrapper(*args, **kwargs):
print(f"Appel de la fonction : {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log_appel
def calculer_total(prix, quantite):
return prix * quantite
calculer_total(10, 5)
# Affiche : Appel de la fonction : calculer_total
Ici, __name__ renvoie le nom de la classe ou de la fonction sous forme de chaîne de caractères, ce qui est extrêmement utile pour le docstring, le débogage et la métaprogrammation.
__name__ et les packages
Dans le contexte des packages (dossiers contenant un fichier __init__.py), __name__ reflète le chemin complet du module :
# Structure :
# mon_projet/
# __init__.py
# core/
# __init__.py
# moteur.py
# Dans mon_projet/core/moteur.py :
print(__name__)
# Quand importé : "mon_projet.core.moteur"
# Quand exécuté directement : "__main__"
Tableau récapitulatif
| Contexte d'exécution | Valeur de __name__ | Exemple |
|---|---|---|
| Script exécuté directement | "__main__" | python script.py |
| Module importé | Nom du module | import script → "script" |
| Module dans un package | Chemin complet | import pkg.mod → "pkg.mod" |
| Attribut d'une classe | Nom de la classe | MaClasse.__name__ → "MaClasse" |
| Attribut d'une fonction | Nom de la fonction | ma_func.__name__ → "ma_func" |
Bonnes pratiques
Voici les règles à suivre pour tirer le meilleur parti de __name__ dans vos projets Python :
1. Toujours utiliser le bloc de garde
Chaque fichier Python susceptible d'être importé ET exécuté devrait contenir un bloc if __name__ == "__main__". C'est une convention universelle et une marque de code professionnel.
# ✅ Bonne pratique
def ma_fonction():
return "Résultat"
if __name__ == "__main__":
print(ma_fonction())
# ❌ Mauvaise pratique
def ma_fonction():
return "Résultat"
print(ma_fonction()) # S'exécute aussi à l'importation !
2. Déléguer à une fonction main()
Plutôt que de placer toute la logique dans le bloc if, créez une fonction main() dédiée. Cela facilite les tests et améliore la lisibilité.
# ✅ Recommandé
def main():
# Toute la logique ici
pass
if __name__ == "__main__":
main()
3. Utiliser __name__ pour le logging
L'utilisation de __name__ dans la configuration du print et du module logging est une pratique standard :
import logging
# Crée un logger avec le nom du module courant
logger = logging.getLogger(__name__)
def ma_fonction():
logger.info("Fonction exécutée")
# Le log affichera le nom du module automatiquement
Cette approche est puissante car elle permet de tracer exactement quel module a émis un message de log, ce qui est indispensable dans les projets de grande envergure.
4. Ne pas modifier __name__
Bien qu'il soit techniquement possible de modifier la valeur de __name__, vous ne devriez jamais le faire. Cette variable est gérée par l'interpréteur Python et la modifier peut entraîner des comportements imprévisibles.
5. Séparer définitions et exécution
Placez toutes vos définitions de fonctions, class et constantes en haut du fichier. Le bloc if __name__ == "__main__" doit être le dernier élément du fichier :
# 1. Imports
import os
import sys
# 2. Constantes
VERSION = "1.0.0"
# 3. Classes et fonctions
class Application:
pass
def demarrer():
pass
# 4. Point d'entrée (toujours en dernier)
if __name__ == "__main__":
demarrer()
Erreurs courantes à éviter
Voici les pièges les plus fréquents liés à __name__ :
Oublier les guillemets autour de __main__
# ❌ Erreur : __main__ sans guillemets n'existe pas comme variable
if __name__ == __main__: # NameError !
pass
# ✅ Correct : c'est une chaîne de caractères
if __name__ == "__main__":
pass
Confondre __name__ du module et de la classe
class MonMoteur:
pass
# __name__ au niveau du module = contexte d'exécution
print(__name__) # "__main__" ou nom du module
# __name__ sur la classe = nom de la classe
print(MonMoteur.__name__) # "MonMoteur"
Exécuter du code au niveau global sans garde
# ❌ Dangereux : ce code s'exécute à chaque import
connexion = creer_connexion_base_de_donnees()
resultat = requete_longue(connexion)
# ✅ Protégé par la garde
if __name__ == "__main__":
connexion = creer_connexion_base_de_donnees()
resultat = requete_longue(connexion)
Questions fréquentes
Que signifie exactement if __name__ == "__main__" en Python ?
Cette condition vérifie si le fichier Python est exécuté directement (et non importé comme module). Quand vous lancez un fichier avec python fichier.py, l'interpréteur attribue la valeur "__main__" à la variable __name__ de ce fichier. La condition est donc vraie et le bloc de code s'exécute. En revanche, si ce fichier est importé par un autre script via import fichier, __name__ vaut "fichier" et le bloc est ignoré. C'est un mécanisme essentiel pour séparer le code réutilisable du code d'exécution.
Peut-on avoir plusieurs blocs if __name__ == "__main__" dans un même fichier ?
Techniquement, oui, Python ne vous en empêchera pas. Cependant, c'est fortement déconseillé. La convention est d'avoir un seul bloc if __name__ == "__main__" placé à la toute fin du fichier. Avoir plusieurs blocs rend le code confus et difficile à maintenir. Si vous avez besoin d'exécuter plusieurs actions, regroupez-les dans une fonction main() unique.
__name__ est-il obligatoire dans tous les fichiers Python ?
Non, __name__ n'est pas obligatoire. La variable existe toujours automatiquement, mais vous n'êtes pas obligé d'utiliser le bloc if __name__ == "__main__". Cependant, il est recommandé de l'ajouter dès que votre fichier contient du code qui ne devrait pas s'exécuter lors d'une importation. Pour les fichiers qui ne sont que des bibliothèques de def (fonctions) ou de class, c'est une bonne pratique d'inclure ce bloc pour y placer des tests rapides.
Comment apprendre à bien utiliser __name__ et structurer ses projets Python ?
Pour maîtriser __name__ et toutes les conventions professionnelles de Python, nous vous recommandons de suivre notre formation dédiée à Python sur Believemy. Vous y apprendrez non seulement la syntaxe du langage, mais aussi les bonnes pratiques de structuration de projets, la gestion des modules et packages, et les patterns utilisés en entreprise. La pratique régulière avec des projets concrets est la meilleure façon d'intégrer ces concepts naturellement dans votre code.