Bien que cette question ait été posée et résolue à plusieurs reprises (ex, aquí , aquí , aquí y aquí ), je pense qu'aucune réponse existante ne permet d'appréhender de manière complète ou concise toutes les implications de l'initiative de l -m
drapeau. C'est pourquoi ce qui suit tentera d'améliorer ce qui a été fait jusqu'à présent.
Introduction (TLDR)
Le -m
Le drapeau fait beaucoup de choses, qui ne sont pas toutes nécessaires en permanence. En bref, il peut être utilisé pour (1) exécuter du code python depuis la ligne de commande via modulename plutôt que filename (2) ajouter un répertoire à sys.path
à utiliser dans import
et (3) exécuter du code python contenant des importations relatives à partir de la ligne de commande.
Préliminaires
Pour expliquer la -m
Il faut d'abord expliquer un peu la terminologie.
L'unité organisationnelle principale de Python est connue sous le nom de module . Les modules se présentent sous deux formes : les modules de code et les modules de paquetage. Un module de code est un fichier qui contient du code exécutable en Python. Un module de paquetage est un répertoire qui contient d'autres modules (soit des modules de code, soit des modules de paquetage). Les modules de code les plus courants sont les suivants *.py
tandis que le type le plus courant de modules de paquetage est constitué de répertoires contenant un fichier __init__.py
fichier.
Python permet d'identifier les modules de deux manières distinctes : le nom du module et le nom du fichier. En général, les modules sont identifiés par leur 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ètes python sont capables de convertir des noms de modules en noms de fichiers en suivant les mêmes quelques règles bien définies. Ces règles s'articulent autour de la fonction sys.path
variable. En modifiant cette variable, on peut changer la façon dont Python résout les noms de modules en noms de fichiers (pour plus d'informations sur la façon de procéder, voir PEP 302 ).
Tous les modules (code et paquetage) peuvent être exécutés (c'est-à-dire 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 où il l'est peuvent changer considérablement. Par exemple, si l'on exécute un module de paquetage via python <filename>
puis <filename>/__main__.py
sera exécutée. D'autre part, si l'on exécute ce même module de paquetage via import <modulename>
alors seulement le __init__.py
sera exécutée.
Développement historique de la -m
Le -m
Le drapeau a été introduit pour la première fois en Python 2.4.1 . Au départ, son seul objectif était de fournir un moyen alternatif d'identifier le module python à exécuter à partir de la ligne de commande. En d'autres termes, si nous connaissions à la fois le <filename>
y <modulename>
pour un module, les deux commandes suivantes sont équivalentes : python <filename> <args>
y python -m <modulename> <args>
. Une contrainte avec cette itération, selon PEP 338 était que -m
ne fonctionne qu'avec les noms de modules de premier niveau (c'est-à-dire les modules qui peuvent être trouvés directement sur sys.path
sans aucun module de paquetage intermédiaire).
Avec l'achèvement de la PEP 338 les -m
a été étendue à la prise en charge des <modulename>
des représentations au-delà du niveau le plus élevé. Cela signifiait des noms tels que http.server
sont désormais pleinement pris en charge. Cette extension signifie également que chaque paquet parent dans le nom du module est désormais évalué (c'est-à-dire que tous les paquets parents __init__.py
ont été évalués) en plus du module référencé par le nom de module lui-même.
La dernière amélioration majeure de la fonctionnalité de -m
est venu avec PEP 366 . Avec cette mise à niveau -m
a acquis la capacité de prendre en charge non seulement les importations absolues, mais aussi les importations relatives explicites lors de l'exécution des modules. Ceci a été réalisé en changeant -m
de manière à ce qu'il fixe le __package__
au module parent du nom de module donné (en plus de tout ce qu'il a déjà fait).
Cas d'utilisation
Il existe deux cas d'utilisation notables pour le -m
drapeau :
-
Pour exécuter des modules à partir de la ligne de commande dont on ne connaît pas le 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 module http.server
mais la plupart des gens connaissent son nom de module, de sorte que nous pouvons l'exécuter à partir de la ligne de commande à l'aide de la commande python -m http.server
.
-
Exécuter un paquet local contenant des importations absolues ou relatives sans avoir à 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.path
plutôt que le répertoire du module. Ce cas d'utilisation est très similaire à l'utilisation de pip install -e .
pour installer un paquet en mode développement/édition.
Lacunes
Avec toutes les améliorations apportées à -m
au fil des ans, il présente toujours une lacune majeure : il ne peut exécuter que des modules écrits en Python (c'est-à-dire, *.py
). Par exemple, si -m
est utilisé pour exécuter un module de code compilé en C, l'erreur suivante sera produite, No code object available for <modulename>
(voir aquí pour plus de détails).
Comparaisons détaillées
Exécution d'un module via une déclaration d'importation (c'est-à-dire, import <modulename>
):
-
sys.path
es no modifié de quelque manière que ce soit
-
__name__
est fixé à la forme absolue de <modulename>
-
__package__
est fixé au paquet parent immédiat dans <modulename>
-
__init__.py
est évalué pour tous les paquets (y compris le sien pour les modules du paquet)
-
__main__.py
es no évalué pour les modules de paquetage ; le code est évalué pour les modules de code
Exécution du module via la ligne de commande avec le nom du fichier (c'est-à-dire, python <filename>
):
-
sys.path
est modifié pour inclure le répertoire final dans <filename>
-
__name__
est fixé à '__main__'
-
__package__
est fixé à None
-
__init__.py
n'est évalué pour aucun paquet (y compris le sien pour les modules du paquet)
-
__main__.py
est évalué pour les modules de paquetage ; le code est évalué pour les modules de code.
Exécution du module via la ligne de commande avec le nom du module (c'est-à-dire, python -m <modulename>
):
-
sys.path
est modifié pour inclure le répertoire actuel
-
__name__
est fixé à '__main__'
-
__package__
est fixé au paquet parent immédiat dans <modulename>
-
__init__.py
est évalué pour tous les paquets (y compris le sien pour les modules du paquet)
-
__main__.py
est évalué pour les modules de paquetage ; le code est évalué pour les modules de code
Conclusion
Le -m
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. La véritable puissance de l'option -m
Cependant, le succès de l'initiative réside dans sa capacité à combiner la puissance de la technologie de l'information et de la communication (TIC). import
(par exemple, prise en charge des importations relatives explicites et des paquets automatiques). __init__
) avec la commodité de la ligne de commande.
0 votes
Veuillez me corriger si je me trompe, mais
-m
semble recherchermymod1
dans le chemin de la bibliothèque par défaut. Exemple :python -m SimpleHTTPServer
fonctionne, alors quepython SimpleHTTPServer
échoue aveccan't open file 'SimpleHTTPServer': [Errno 2] No such file or directory
.15 votes
En fait, j'ai trouvé la réponse ici plus claire : stackoverflow.com/questions/46319694/