Bien que cette question ait été posée et répondu à plusieurs reprises (par exemple, ici , ici , ici et ici ), à mon avis, aucune réponse existante ne rend compte de manière complète ou concise toutes les implications du -mdrapeau. Par conséquent, ce qui suit tentera d'améliorer ce qui a précédé.
Introduction (TLDR)
La -mcommande fait beaucoup de choses dont toutes ne seront pas nécessairement nécessaires tout le temps. En bref, il: (1) permet aux scripts python d'être exécutés via le nom de module plutôt que le nom de fichier (2) permet de choisir un répertoire à ajouter sys.pathpour la importrésolution et (3) permet aux scripts python avec des importations relatives d'être exécutés à partir de la ligne de commande .
Préliminaires
Pour expliquer le -mdrapeau, nous devons d'abord clarifier un peu la terminologie.
Premièrement, l'unité organisationnelle principale de Python est connue sous le nom de module . Les modules sont disponibles en deux versions: les modules de code et les modules de package. Un module de code est un fichier contenant du code exécutable python. Un module de package est un répertoire qui contient d'autres modules (soit des modules de code, soit des modules de package). Les types de modules de code *.pyles plus courants sont les fichiers tandis que les types les plus courants de modules de packages sont les répertoires contenant un __init__.pyfichier.
Deuxièmement, tous les modules peuvent être identifiés de manière unique de deux manières distinctes: <modulename>et <filename>. Les modules sont le plus souvent identifiés par nom de module dans le code Python (par exemple, import <modulename>) et par nom de fichier sur la ligne de commande (par exemple, python <filename>). Tous les interpréteurs Python peuvent convertir les noms de modules en noms de fichiers via un ensemble de règles bien définies. Ces règles dépendent de la sys.pathvariable et par conséquent le mappage peut être modifié en changeant cette valeur (pour plus d'informations sur la façon dont cela est fait, voir PEP 302 ).
Troisièmement, tous les modules (à la fois le code et le package) peuvent être exécutés (nous entendons par là que le code associé au module sera évalué par l'interpréteur Python). En fonction de la méthode d'exécution et du type de module, le code évalué et le moment peuvent changer un peu. Par exemple, si on exécute un module de package via python <filename>alors <filename>/__init__.pysera évalué suivi de <filename>/__main__.py. D'un autre côté, si l'on exécute ce même module de package via import <modulename>alors seuls les packages __init__.pyseront exécutés.
Développement historique de -m
L'indicateur -m a été introduit pour la première fois dans Python 2.4.1 . Initialement, son seul objectif était de fournir un moyen alternatif d'identifier un module python à exécuter. Autrement dit, si nous connaissions à la fois le <filename>et <modulename>pour un module, les deux commandes suivantes étaient équivalentes: python <filename> <args>et python -m <modulename> <args>. De plus, selon PEP 338, cette itération -mne fonctionnait qu'avec des noms de modules de premier niveau (c'est-à-dire des modules qui pouvaient être trouvés directement sur sys.path sans aucun paquetage intermédiaire).
Avec l'achèvement du PEP 338, la -mfonctionnalité a été étendue pour prendre en charge les <modulename>représentations au-delà des noms de module de niveau supérieur. Cela signifiait des noms tels que http.serverdésormais entièrement pris en charge. Cette amélioration signifiait également que tous les packages d'un module étaient désormais chargés (c'est-à-dire que tous les __init__.pyfichiers de packages étaient évalués), avec le module lui-même.
La dernière amélioration majeure des fonctionnalités -mest venue avec PEP 366 . Avec cette mise -mà jour, nous avons acquis la capacité de prendre en charge non seulement les importations absolues, mais également les importations relatives explicites. Ceci a été réalisé en modifiant la __package__variable du module nommé dans la -mcommande.
Cas d'utilisation
Il existe deux cas d'utilisation notables pour l'indicateur -m:
Exécuter des modules à partir de la ligne de commande dont on peut ne pas connaître leur nom de fichier. Ce cas d'utilisation tire parti du fait que l'interpréteur Python sait comment convertir les noms de modules en noms de fichiers. Ceci est particulièrement avantageux lorsque l'on veut exécuter des modules stdlib ou des modules tiers à partir de la ligne de commande. Par exemple, très peu de gens connaissent le nom de fichier du http.servermodule mais la plupart des gens connaissent son nom de module afin que nous puissions l'exécuter à partir de la ligne de commande en utilisant python -m http.server.
Pour exécuter un package local contenant des importations absolues sans avoir besoin de l'installer. Ce cas d'utilisation est détaillé dans PEP 338 et tire parti du fait que le répertoire de travail actuel est ajouté sys.pathplutôt que le répertoire du module. Ce cas d'utilisation est très similaire à l'utilisation pip install -e .pour installer un package en mode développement / édition.
Les lacunes
Avec toutes les améliorations apportées au -mfil des ans, il présente encore un inconvénient majeur: il ne peut exécuter que des modules de code écrits en python (c'est-à-dire * .py). Par exemple, si -mest utilisé pour exécuter un module de code compilé en C, l'erreur suivante sera produite No code object available for <modulename>(voir ici pour plus de détails).
Comparaisons détaillées
Effets de l'exécution du module via la commande python (ie, python <filename>):
sys.path est modifié pour inclure le répertoire final dans <filename>
__name__ est réglé sur '__main__'
__package__ est réglé sur None
__init__.py n'est évalué pour aucun package (y compris le sien pour les modules de package)
__main__.pyest évalué pour les modules de package; le code est évalué pour les modules de code.
Effets de l'exécution du module via une instruction d'importation (c'est-à-dire import <modulename>):
sys.pathest pas modifié de quelque façon
__name__ prend la forme absolue de <modulename>
__package__ est défini sur le package parent immédiat dans <modulename>
__init__.py est évalué pour tous les packages (y compris le sien pour les modules de package)
__main__.pyn'est pas évalué pour les modules de package; le code est évalué pour les modules de code
Effets de l'exécution du module via l'option -m (c'est-à-dire python -m <modulename>):
sys.path est modifié pour inclure le répertoire courant
__name__ est réglé sur '__main__'
__package__ est défini sur le package parent immédiat dans <modulename>
__init__.py est évalué pour tous les packages (y compris le sien pour les modules de package)
__main__.pyest évalué pour les modules de package; le code est évalué pour les modules de code
Conclusion
L' -mindicateur est, dans sa forme la plus simple, un moyen d'exécuter des scripts python à partir de la ligne de commande en utilisant des noms de modules plutôt que des noms de fichiers. De plus, -mfournit des fonctionnalités supplémentaires qui combinent la puissance des importinstructions (par exemple, la prise en charge d'importations relatives explicites et l' __init__évaluation automatique des packages ) avec la commodité de la ligne de commande python.
-msemble recherchermymod1dans le chemin de la bibliothèque par défaut. Exemple:python -m SimpleHTTPServerfonctionne, maispython SimpleHTTPServeréchoue aveccan't open file 'SimpleHTTPServer': [Errno 2] No such file or directory.