Pourriez-vous m'expliquer quelle est la différence entre appeler
python -m mymod1 mymod2.py args
et
python mymod1.py mymod2.py args
Il semble dans les deux cas mymod1.py
s'appelle et sys.argv
est
['mymod1.py', 'mymod2.py', 'args']
Alors à quoi sert le -m
commutateur?
python
command-line
module
package
Charles Brunet
la source
la source
-m
semble recherchermymod1
dans le chemin de la bibliothèque par défaut. Exemple:python -m SimpleHTTPServer
fonctionne, maispython SimpleHTTPServer
échoue aveccan't open file 'SimpleHTTPServer': [Errno 2] No such file or directory
.Réponses:
La première ligne de la
Rationale
section de la PEP 338 dit:Ainsi, vous pouvez spécifier n'importe quel module dans le chemin de recherche de Python de cette façon, pas seulement les fichiers dans le répertoire actuel. Vous avez raison, cela
python mymod1.py mymod2.py args
a exactement le même effet. La première ligne de laScope of this proposal
section indique:Avec
-m
plus, c'est possible, comme travailler avec des modules qui font partie d'un package, etc. C'est ce dont parle le reste de PEP 338. Lisez-le pour plus d'informations.la source
-m
estpython -m SimpleHTTPServer
. Vraiment pratique lorsque j'ai besoin de partager des fichiers sans utiliser de clé USB.python -m http.server
et c'est toujours génial!python -m package.subpackage.module
et la machine de résolution normale sera utilisée, vous n'avez pas à indiquer le.py
fichier exact . 2) Il est possible d'effectuer des importations relatives à partir du module exécuté, sans aucune solution de contournement, car son package sera chargé en cours de route. 3) Les importations absolues seront basées sur votre répertoire actuel, et non sur le répertoire où se trouve le.py
fichier (''
est à la tête desys.path
, plutôt que/path/to/my
si le script est à/path/to/my/script.py
).__main__.py
fichier. La plupart ne le font pas et vont casser par exemplepython -m sys 'print(sys.version)'
avecpython: No code object available for sys
. Je vous suggère de préciser cela dans la réponse.Cela vaut la peine de mentionner que cela ne fonctionne que si le package contient un fichier.
__main__.py
Sinon, ce package ne peut pas être exécuté directement.L'interpréteur python recherchera un
__main__.py
fichier dans le chemin du package à exécuter. C'est équivalent à:Il exécutera le contenu après:
la source
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
-m
drapeau. Par conséquent, ce qui suit tentera d'améliorer ce qui a précédé.Introduction (TLDR)
La
-m
commande 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 à ajoutersys.path
pour laimport
ré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
-m
drapeau, 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
*.py
les plus courants sont les fichiers tandis que les types les plus courants de modules de packages sont les répertoires contenant un__init__.py
fichier.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 lasys.path
variable 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__.py
sera évalué suivi de<filename>/__main__.py
. D'un autre côté, si l'on exécute ce même module de package viaimport <modulename>
alors seuls les packages__init__.py
seront 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>
etpython -m <modulename> <args>
. De plus, selon PEP 338, cette itération-m
ne 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
-m
fonctionnalité 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 quehttp.server
dé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__.py
fichiers de packages étaient évalués), avec le module lui-même.La dernière amélioration majeure des fonctionnalités
-m
est 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-m
commande.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.server
module mais la plupart des gens connaissent son nom de module afin que nous puissions l'exécuter à partir de la ligne de commande en utilisantpython -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.path
plutôt que le répertoire du module. Ce cas d'utilisation est très similaire à l'utilisationpip install -e .
pour installer un package en mode développement / édition.Les lacunes
Avec toutes les améliorations apportées au
-m
fil 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-m
est utilisé pour exécuter un module de code compilé en C, l'erreur suivante sera produiteNo 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é surNone
__init__.py
n'est évalué pour aucun package (y compris le sien pour les modules de package)__main__.py
est é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.path
est 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__.py
n'est pas évalué pour les modules de package; le code est évalué pour les modules de codeEffets 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__.py
est évalué pour les modules de package; le code est évalué pour les modules de codeConclusion
L'
-m
indicateur 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,-m
fournit des fonctionnalités supplémentaires qui combinent la puissance desimport
instructions (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.la source
python -m packagename
comme mentionné ici: stackoverflow.com/a/53772635/1779091