Définition des fonctions principales en Python

Définition des fonctions principales en Python

De nombreux langages de programmation ont une fonction spéciale qui est automatiquement exécutée lorsqu'un système d'exploitation commence à exécuter un programme. Cette fonction est généralement appeléemain() et doit avoir un type de retour et des arguments spécifiques selon le standard du langage. D'un autre côté, l'interpréteur Python exécute des scripts commençant en haut du fichier, et il n'y a aucune fonction spécifique que Python exécute automatiquement.

Néanmoins, avoir un point de départ défini pour l'exécution d'un programme est utile pour comprendre comment fonctionne un programme. Les programmeurs Python ont trouvé plusieurs conventions pour définir ce point de départ.

À la fin de cet article, vous comprendrez:

  • Qu'est-ce que la variable spéciale__name__ et comment Python la définit

  • Pourquoi vous voudriez utiliser unmain() en Python

  • Quelles conventions existe-t-il pour définirmain() en Python

  • Quelles sont les meilleures pratiques pour le code à mettre dans vosmain()

Free Bonus:Click here to get access to a chapter from Python Tricks: The Book qui vous montre les meilleures pratiques de Python avec des exemples simples que vous pouvez appliquer instantanément pour écrire du code + Pythonic plus beau.

Un main Python basique ()

Dans certains scripts Python, vous pouvez voir une définition de fonction et une instruction conditionnelle qui ressemble à l'exemple ci-dessous:

def main():
    print("Hello World!")

if __name__ == "__main__":
    main()

Dans ce code, il existe une fonction appeléemain() qui imprime la phraseHello World! lorsque l'interpréteur Python l'exécute. Il existe également une instruction conditionnelle (ouif) qui vérifie la valeur de__name__ et la compare à la chaîne"__main__". Lorsque l'instructionif est évaluée àTrue, l'interpréteur Python exécutemain(). Vous pouvez en savoir plus sur les instructions conditionnelles dansConditional Statements in Python.

Ce modèle de code est assez courant dans les fichiers Python que vous voulez êtreexecuted as a script etimported in another module. Pour aider à comprendre comment ce code s'exécutera, vous devez d'abord comprendre comment l'interpréteur Python définit__name__ en fonction de la manière dont le code est exécuté.

Modes d'exécution en Python

Il existe deux méthodes principales pour demander à l'interpréteur Python d'exécuter ou d'utiliser du code:

  1. Vous pouvez exécuter le fichier Python en tant quescript en utilisant la ligne de commande.

  2. Vous pouvezimport le code d'un fichier Python dans un autre fichier ou dans l'interpréteur interactif.

Vous pouvez en savoir plus sur ces approches dansHow to Run Your Python Scripts. Quelle que soit la manière d'exécuter votre code que vous utilisez, Python définit une variable spéciale appelée__name__ qui contient une chaîne dont la valeur dépend de la manière dont le code est utilisé.

Nous allons utiliser cet exemple de fichier, enregistré sousexecution_methods.py, pour explorer comment le comportement du code change en fonction du contexte:

print("This is my file to test Python's execution methods.")
print("The variable __name__ tells me which context this file is running in.")
print("The value of __name__ is:", repr(__name__))

Dans ce fichier, trois appels àprint() sont définis. Les deux premiers impriment quelques phrases d'introduction. Le troisièmeprint() affichera d'abord la phraseThe value of __name__ is, puis il affichera la représentation de la variable__name__ en utilisant lesrepr() intégrés de Python.

En Python,repr() affiche la représentation imprimable d'un objet. Cet exemple utiliserepr() pour souligner que la valeur de__name__ est une chaîne. Vous pouvez en savoir plus surrepr() dans lesPython documentation.

Vous verrez les motsfile,module etscript utilisés tout au long de cet article. Pratiquement, il n'y a pas beaucoup de différence entre eux. Cependant, il existe de légères différences de signification qui soulignent le but d'un morceau de code:

  1. File: En général, un fichier Python est un fichier contenant du code. La plupart des fichiers Python ont l'extension.py.

  2. Script: Un script Python est un fichier que vous avez l'intention d'exécuter à partir de la ligne de commande pour accomplir une tâche.

  3. Module: Un module Python est un fichier que vous souhaitez importer depuis un autre module ou un script, ou depuis l'interpréteur interactif. Vous pouvez en savoir plus sur les modules dans lesPython documentation.

Cette distinction est également discutée enHow to Run Your Python Scripts.

Exécution à partir de la ligne de commande

Dans cette approche, vous souhaitez exécuter votre script Python à partir de la ligne de commande.

Lorsque vous exécutez un script, vous ne pourrez pas définir de manière interactive le code que l'interpréteur Python exécute. Les détails sur la façon dont vous pouvez exécuter Python à partir de votre ligne de commande ne sont pas si importants aux fins de cet article, mais vous pouvez développer la zone ci-dessous pour en savoir plus sur les différences entre la ligne de commande sur Windows, Linux et macOS.

Vous devez maintenant exécuter le scriptexecution_methods.py à partir de la ligne de commande, comme indiqué ci-dessous:

$ python3 execution_methods.py
This is my file to test Python's execution methods.
The variable __name__ tells me which context this file is running in.
The value of __name__ is: '__main__'

Dans cet exemple, vous pouvez voir que__name__ a la valeur'__main__', où les symboles de guillemet (') vous indiquent que la valeur est de type chaîne.

N'oubliez pas qu'en Python, il n'y a aucune différence entre les chaînes définies avec des guillemets simples (') et des guillemets doubles ("). Vous pouvez en savoir plus sur la définition de chaînes dansBasic Data Types in Python.

Vous trouverez une sortie identique si vous incluez unshebang line dans votre script et l'exécutez directement (./execution_methods.py), ou utilisez la magie de%run dans IPython ou Jupyter Notebooks.

Vous pouvez également voir des scripts Python exécutés à partir de packages en ajoutant l'argument-m à la commande. Le plus souvent, vous verrez ceci recommandé lorsque vous utilisezpip:python3 -m pip install package_name.

L'ajout de l'argument-m exécute le code dans le module__main__.py d'un package. Vous pouvez trouver plus d'informations sur le fichier__main__.py dansHow to Publish an Open-Source Python Package to PyPI.

Dans ces trois cas,__name__ a la même valeur: la chaîne'__main__'.

Technical detail: La documentation Python définit spécifiquement quand__name__ aura la valeur'__main__':

Le__name__ d'un module est défini égal à'__main__' lorsqu'il est lu à partir d'une entrée standard, d'un script ou d'une invite interactive. (https://docs.python.org/3/library/main.html [Source])

__name__ est stocké dans l'espace de noms global du module avec les__doc__,__package__ et d'autres attributs. Vous pouvez en savoir plus sur ces attributs dans lesPython Data Model documentation et, en particulier pour les modules et les packages, dans lesPython Import documentation.

Importation dans un module ou l'interpréteur interactif

Voyons maintenant la deuxième façon dont l'interpréteur Python exécutera votre code: les importations. Lorsque vous développez un module ou un script, vous souhaiterez probablement tirer parti des modules que quelqu'un d'autre a déjà construits, ce que vous pouvez faire avec le mot-cléimport.

Pendant le processus d'importation, Python exécute les instructions définies dans le module spécifié (mais uniquement le tempsfirst que vous importez un module). Pour montrer les résultats de l'importation de votre fichierexecution_methods.py, démarrez l'interpréteur Python interactif, puis importez votre fichierexecution_methods.py:

>>>

>>> import execution_methods
This is my file to test Python's execution methods.
The variable __name__ tells me which context this file is running in.
The value of __name__ is: 'execution_methods'

Dans cette sortie de code, vous pouvez voir que l'interpréteur Python exécute les trois appels àprint(). Les deux premières lignes de sortie sont exactement les mêmes que lorsque vous avez exécuté le fichier en tant que script sur la ligne de commande car il n'y a aucune variable dans aucune des deux premières lignes. Cependant, il y a une différence dans la sortie des troisièmesprint().

Lorsque l'interpréteur Python importe du code, la valeur de__name__ est définie pour être identique au nom du module en cours d'importation. Vous pouvez le voir dans la troisième ligne de sortie ci-dessus. __name__ a la valeur'execution_methods', qui est le nom du fichier.py à partir duquel Python importe.

Notez que si vousimport le module à nouveau sans quitter Python, il n'y aura pas de sortie.

Note: Pour plus d'informations sur le fonctionnement de l'importation en Python, consultez lesofficial documentation ainsi que lesAbsolute vs Relative Imports in Python.

Meilleures pratiques pour les fonctions principales de Python

Maintenant que vous pouvez voir les différences dans la façon dont Python gère ses différents modes d'exécution, il est utile pour vous de connaître quelques bonnes pratiques à utiliser. Celles-ci s'appliqueront chaque fois que vous voudrez écrire du code que vous pouvez exécuter en tant que script d'importationand dans un autre module ou une session interactive.

Vous découvrirez quatre bonnes pratiques pour vous assurer que votre code peut servir un double objectif:

  1. Mettez la plupart du code dans une fonction ou une classe.

  2. Utilisez__name__ pour contrôler l'exécution de votre code.

  3. Créez une fonction appeléemain() pour contenir le code que vous souhaitez exécuter.

  4. Appelez d'autres fonctions depuismain().

Placer le plus de code dans une fonction ou une classe

N'oubliez pas que l'interpréteur Python exécute tout le code d'un module lorsqu'il importe le module. Parfois, le code que vous écrivez aura des effets secondaires que vous souhaitez que l'utilisateur contrôle, tels que:

  • Exécuter un calcul qui prend beaucoup de temps

  • Écriture dans un fichier sur le disque

  • Impression d'informations qui encombreraient le terminal de l'utilisateur

Dans ces cas, vous souhaitez que l'utilisateur contrôle le déclenchement de l'exécution de ce code, plutôt que de laisser l'interpréteur Python exécuter le code lors de l'importation de votre module.

Par conséquent, la meilleure pratique est deinclude most code inside a function or a class. En effet, lorsque l'interpréteur Python rencontre les mots-clésdef ouclass, il ne stocke ces définitions que pour une utilisation ultérieure et ne les exécute pas tant que vous ne le lui demandez pas.

Enregistrez le code ci-dessous dans un fichier appelébest_practices.py pour illustrer cette idée:

 1 from time import sleep
 2
 3 print("This is my file to demonstrate best practices.")
 4
 5 def process_data(data):
 6     print("Beginning data processing...")
 7     modified_data = data + " that has been modified"
 8     sleep(3)
 9     print("Data processing finished.")
10     return modified_data

Dans ce code, vous importez d'abordsleep() depuis lestime module.

sleep() met l'interpréteur en pause pendant le nombre de secondes que vous donnez comme argument et produira une fonction qui prend beaucoup de temps à s'exécuter pour cet exemple. Ensuite, vous utilisezprint() pour imprimer une phrase décrivant le but de ce code.

Ensuite, vous définissez une fonction appeléeprocess_data() qui fait cinq choses:

  1. Imprime une sortie pour indiquer à l'utilisateur que le traitement des données démarre

  2. Modifie les données d'entrée

  3. Suspend l'exécution pendant trois secondes à l'aide desleep()

  4. Imprime une sortie pour indiquer à l'utilisateur que le traitement est terminé

  5. Renvoie les données modifiées

Exécuter le fichier de bonnes pratiques sur la ligne de commande

Maintenant, que se passera-t-il lorsque vous exécuterez ce fichier en tant que script sur la ligne de commande?

L'interpréteur Python exécutera les lignesfrom time import sleep etprint() qui sont en dehors de la définition de la fonction, puis il créera la définition de la fonction appeléeprocess_data(). Ensuite, le script se terminera sans rien faire de plus, car le script n'a pas de code qui exécuteprocess_data().

Le bloc de code ci-dessous montre le résultat de l'exécution de ce fichier en tant que script:

$ python3 best_practices.py
This is my file to demonstrate best practices.

La sortie que nous pouvons voir ici est le résultat des premiersprint(). Notez que l'importation depuistime et la définition deprocess_data() ne produisent aucune sortie. Plus précisément, les sorties des appels àprint() qui sont à l'intérieur de la définition deprocess_data() ne sont pas imprimées!

Importer le fichier de bonnes pratiques dans un autre module ou l'interpréteur interactif

Lorsque vous importez ce fichier dans une session interactive (ou un autre module), l'interpréteur Python effectuera exactement les mêmes étapes que lorsqu'il exécute le fichier en tant que script.

Une fois que l'interpréteur Python importe le fichier, vous pouvez utiliser toutes les variables, classes ou fonctions définies dans le module que vous avez importé. Pour le démontrer, nous utiliserons l'interpréteur interactif Python. Démarrez l'interpréteur interactif puis tapezimport best_practices:

>>>

>>> import best_practices
This is my file to demonstrate best practices.

La seule sortie de l'importation du fichierbest_practices.py provient du premier appelprint() défini en dehors deprocess_data(). L'importation à partir detime et la définition deprocess_data() ne produisent aucune sortie, tout comme lorsque vous exécutez le code à partir de la ligne de commande.

Utilisezif __name__ == "main" pour contrôler l'exécution de votre code

Que faire si vous voulez queprocess_data() s'exécute lorsque vous exécutez le script à partir de la ligne de commande mais pas lorsque l'interpréteur Python importe le fichier?

Vous pouvezuse the if __name__ == "main" idiom to determine the execution context et exécuter conditionnellementprocess_data() uniquement lorsque__name__ est égal à"__main__". Ajoutez le code ci-dessous au bas de votre fichierbest_practices.py:

11 if __name__ == "__main__":
12     data = "My data read from the Web"
13     print(data)
14     modified_data = process_data(data)
15     print(modified_data)

Dans ce code, vous avez ajouté une instruction conditionnelle qui vérifie la valeur de__name__. Cette condition sera évaluée àTrue lorsque__name__ est égal à la chaîne"__main__". N'oubliez pas que la valeur spéciale de"__main__" pour la variable__name__ signifie que l'interpréteur Python exécute votre script et ne l'importe pas.

À l'intérieur du bloc conditionnel, vous avez ajouté quatre lignes de code (lignes 12, 13, 14 et 15):

  • Lines 12 and 13: Vous créez une variabledata qui stocke les données que vous avez acquises sur le Web et l’imprime.

  • Line 14: Vous traitez les données.

  • Line 15: Vous imprimez les données modifiées.

Maintenant, exécutez votre scriptbest_practices.py à partir de la ligne de commande pour voir comment la sortie va changer:

$ python3 best_practices.py
This is my file to demonstrate best practices.
My data read from the Web
Beginning data processing...
Data processing finished.
My data read from the Web that has been modified

Tout d'abord, la sortie affiche le résultat de l'appelprint() en dehors deprocess_data().

Après cela, la valeur dedata est imprimée. Cela s'est produit parce que la variable__name__ a la valeur"__main__" lorsque l'interpréteur Python exécute le fichier en tant que script, donc l'instruction conditionnelle évaluée àTrue.

Ensuite, votre script a appeléprocess_data() et a transmisdata pour modification. Lorsqueprocess_data() s'exécute, il imprime des messages d'état sur la sortie. Enfin, la valeur demodified_data est imprimée.

Vous devez maintenant vérifier ce qui se passe lorsque vous importez le fichierbest_practices.py depuis l'interpréteur interactif (ou un autre module). L'exemple ci-dessous illustre cette situation:

>>>

>>> import best_practices
This is my file to demonstrate best practices.

Notez que vous obtenez le même comportement qu'avant d'avoir ajouté l'instruction conditionnelle à la fin du fichier! En effet, la variable__name__ avait la valeur"best_practices", donc Python n'a pas exécuté le code à l'intérieur du bloc, y comprisprocess_data(), car l'instruction conditionnelle était évaluée àFalse.

Créer une fonction appelée main () pour contenir le code que vous souhaitez exécuter

Vous pouvez maintenant écrire du code Python qui peut être exécuté à partir de la ligne de commande en tant que script et importé sans effets secondaires indésirables. Ensuite, vous allez apprendre à écrire votre code pour permettre aux autres programmeurs Python de suivre facilement ce que vous voulez dire.

De nombreux langages, tels que C, C +, Java, et plusieurs autres, définissent une fonction spéciale qui doit être appelée «+ main ()» que le système d'exploitation appelle automatiquement lorsqu'il exécute le programme compilé. Cette fonction est souvent appelée lesentry point car c'est là que l'exécution entre dans le programme.

En revanche, Python n'a pas de fonction spéciale qui sert de point d'entrée à un script. Vous pouvez réellement donner à la fonction point d'entrée dans un script Python le nom que vous voulez!

Bien que Python n'attribue aucune signification à une fonction nomméemain(), la meilleure pratique consiste quand même àname the entry point function main(). De cette façon, tout autre programmeur qui lit votre script sait immédiatement que cette fonction est le point de départ du code qui accomplit la tâche principale du script.

De plus,main() doit contenir tout code que vous souhaitez exécuter lorsque l'interpréteur Python exécute le fichier. C'est mieux que de mettre le code directement dans le bloc conditionnel car un utilisateur peut réutiliser `main ()` s'il importe votre module.

Modifiez le fichierbest_practices.py pour qu'il ressemble au code ci-dessous:

 1 from time import sleep
 2
 3 print("This is my file to demonstrate best practices.")
 4
 5 def process_data(data):
 6     print("Beginning data processing...")
 7     modified_data = data + " that has been modified"
 8     sleep(3)
 9     print("Data processing finished.")
10     return modified_data
11
12 def main():
13     data = "My data read from the Web"
14     print(data)
15     modified_data = process_data(data)
16     print(modified_data)
17
18 if __name__ == "__main__":
19     main()

Dans cet exemple, vous avez ajouté la définition demain() qui inclut le code qui était auparavant à l'intérieur du bloc conditionnel. Ensuite, vous avez modifié le bloc conditionnel pour qu'il exécutemain(). Si vous exécutez ce code en tant que script ou l'importez, vous obtiendrez la même sortie que dans la section précédente.

Appeler d'autres fonctions depuis main ()

Une autre pratique courante en Python est dehave main() execute other functions, plutôt que d'inclure le code d'accomplissement de la tâche dansmain(). Cela est particulièrement utile lorsque vous pouvez composer votre tâche globale à partir de plusieurs sous-tâches plus petites qui peuvent s'exécuter indépendamment.

Par exemple, vous pouvez avoir un script qui effectue les opérations suivantes:

  1. Lit un fichier de données à partir d'une source qui peut être une base de données, un fichier sur le disque ou une API Web

  2. Traite les données

  3. Écrit les données traitées dans un autre emplacement

Si vous implémentez chacune de ces sous-tâches dans des fonctions distinctes, il est facile pour vous (ou un autre utilisateur) de réutiliser quelques-unes des étapes et d'ignorer celles que vous ne voulez pas. Ensuite, vous pouvez créer un flux de travail par défaut dansmain(), et vous pouvez avoir le meilleur des deux mondes.

L'application de cette pratique à votre code est un jugement de votre part. La division du travail en plusieurs fonctions facilite la réutilisation mais augmente la difficulté pour quelqu'un d'autre d'essayer d'interpréter votre code car il doit suivre plusieurs sauts dans le flux du programme.

Modifiez votre fichierbest_practices.py pour qu'il ressemble au code ci-dessous:

 1 from time import sleep
 2
 3 print("This is my file to demonstrate best practices.")
 4
 5 def process_data(data):
 6     print("Beginning data processing...")
 7     modified_data = data + " that has been modified"
 8     sleep(3)
 9     print("Data processing finished.")
10     return modified_data
11
12 def read_data_from_web():
13     print("Reading data from the Web")
14     data = "Data from the web"
15     return data
16
17 def write_data_to_database(data):
18     print("Writing data to a database")
19     print(data)
20
21 def main():
22     data = read_data_from_web()
23     modified_data = process_data(data)
24     write_data_to_database(modified_data)
25
26 if __name__ == "__main__":
27     main()

Dans cet exemple de code, les 10 premières lignes du fichier ont le même contenu qu'auparavant. La deuxième définition de fonction sur la ligne 12 crée et renvoie des exemples de données, et la troisième définition de fonction sur la ligne 17 simule l'écriture des données modifiées dans une base de données.

À la ligne 21,main() est défini. Dans cet exemple, vous avez modifiémain() pour qu'il appelle tour à tour les fonctions de lecture de données, de traitement de données et d'écriture de données.

Tout d'abord, ledata est créé à partir deread_data_from_web(). Cedata est passé àprocess_data(), qui renvoie lesmodified_data. Enfin,modified_data est passé danswrite_data_to_database().

Les deux dernières lignes du script sont le bloc conditionnel qui vérifie__name__ et exécutemain() si l'instructionif estTrue.

Maintenant, vous pouvez exécuter l'intégralité du pipeline de traitement à partir de la ligne de commande, comme indiqué ci-dessous:

$ python3 best_practices.py
This is my file to demonstrate best practices.
Reading data from the Web
Beginning data processing...
Data processing finished.
Writing processed data to a database
Data from the web that has been modified

Dans la sortie de cette exécution, vous pouvez voir que l'interpréteur Python a exécutémain(), qui a exécutéread_data_from_web(),process_data() etwrite_data_to_database(). Cependant, vous pouvez également importer le fichierbest_practices.py et réutiliserprocess_data() pour une autre source de données d'entrée, comme indiqué ci-dessous:

>>>

>>> import best_practices as bp
This is my file to demonstrate best practices.
>>> data = "Data from a file"
>>> modified_data = bp.process_data(data)
Beginning data processing...
Data processing finished.
>>> bp.write_data_to_database(modified_data)
Writing processed data to a database
Data from a file that has been modified

Dans cet exemple, vous avez importébest_practices et raccourci le nom enbp pour ce code.

Le processus d'importation a amené l'interpréteur Python à exécuter toutes les lignes de code dans le fichierbest_practices.py, de sorte que la sortie affiche la ligne expliquant le but du fichier.

Ensuite, vous avez stocké les données d'un fichier dansdata au lieu de lire les données sur le Web. Ensuite, vous avez réutiliséprocess_data()+`and `+write_data_to_database() du fichierbest_practices.py. Dans ce cas, vous avez profité de la réutilisation de votre code au lieu de définir toute la logique dansmain().

Résumé des meilleures pratiques relatives aux fonctions principales de Python

Voici quatre bonnes pratiques clés concernantmain() en Python que vous venez de voir:

  1. Mettez du code qui prend beaucoup de temps à exécuter ou qui a d'autres effets sur l'ordinateur dans une fonction ou une classe, afin que vous puissiez contrôler exactement quand ce code est exécuté.

  2. Utilisez les différentes valeurs de__name__ pour déterminer le contexte et modifier le comportement de votre code avec une instruction conditionnelle.

  3. Vous devez nommer votre fonction de point d'entréemain() afin de communiquer l'intention de la fonction, même si Python n'attribue aucune signification particulière à une fonction nomméemain().

  4. Si vous souhaitez réutiliser les fonctionnalités de votre code, définissez la logique dans les fonctions en dehors demain() et appelez ces fonctions dansmain().

Conclusion

Toutes nos félicitations! Vous savez maintenant créer des fonctions Pythonmain().

Vous avez appris ce qui suit:

  • Connaître la valeur de la variable__name__ est important pour écrire du code qui sert le double objectif de script exécutable et de module importable.

  • __name__ prend des valeurs différentes selon la façon dont vous avez exécuté votre fichier Python. __name__ sera égal à:

    • "__main__" lorsque le fichier est exécuté depuis la ligne de commande ou avecpython -m (pour exécuter le fichier__main__.py d'un package)

    • Le nom du module, si le module est importé

  • Les programmeurs Python ont développé un ensemble de bonnes pratiques à utiliser lorsque vous souhaitez développer du code réutilisable.

Vous êtes maintenant prêt à écrire du code de fonction Pythonmain()génial!