Obwohl diese Frage mehrmals gestellt und beantwortet wurde (z. B. hier , hier , hier und hier ), erfasst meiner Meinung nach keine vorhandene Antwort alle Implikationen der -m
Flagge vollständig oder präzise . Daher wird im Folgenden versucht, das bisherige zu verbessern.
TLDR
Der -m
Befehl erledigt viele Dinge, die nicht unbedingt immer benötigt werden. Kurz gesagt: (1) ermöglicht die Ausführung von Python-Skripten über den Modulnamen anstelle des Dateinamens. (2) ermöglicht die Auswahl eines Verzeichnisses, das sys.path
zur import
Auflösung hinzugefügt werden soll, und (3) ermöglicht, dass Python-Skripte mit relativen Importen so funktionieren, als ob sie es wären angerufen über import
.
Vorbereitungen
Um die Bedeutung der -m
Flagge zu verstehen , muss eine kleine Terminologie klargestellt werden.
Erstens werden Dateien, die Python ausführen kann, als Module bezeichnet. Normalerweise sind die Module, die uns interessieren, *.py
Dateien, aber nicht immer. Beispielsweise ist es möglich, Python-Module für leistungskritischen Code in C zu schreiben. Diese Unterscheidung wird später wichtig. Im Moment reicht es zu wissen, dass Nicht-Paket-Module Dateien sind.
Zweitens identifiziert Python Module über eine eindeutige <modulename>
Kennung (z import <modulename>
. B. ). Für jedes Unikat <modulename>
gibt es auch irgendwo auf dem Computer eine eindeutige Datei mit einem eigenen Unikat <filename>
. Python Dolmetscher folgen einer Reihe von gut definierten Regeln gebaut um sys.path
eine zur Karte <modulename>
zu einem <filename>
(mehr darüber , wie dies geschehen ist , siehe PEP 302 ).
Historische Entwicklung von -m
Mit Blick auf die Vorbereitungen -m
kann im einfachsten Sinne erklärt werden, dass Python angewiesen wird, ein Modul zu finden, über das ausgeführt werden soll, <modulename>
anstatt <filename>
. Das heißt, wenn entweder ein <filename>
oder <modulename>
für dasselbe Modul gegeben ist, sind die folgenden zwei Befehle äquivalent python <filename>
oder python -m <modulename>
.
In der ursprünglichen Version 2.4.1, in -m
der hinzugefügt wurde, wurden lediglich Module von gesucht und ausgeführt <modulename>
(wobei zusätzlich das aktuelle Verzeichnis hinzugefügt wurde, sys.path
damit auch lokale Module gefunden werden konnten). Gemäß PEP 338 wurde auch die ursprüngliche Implementierung eingeschränkt, so dass -m
keine Modulnamen in Paketen referenziert werden konnten (dh die Version 2.4.1 würde den Modulnamen nicht unterstützen, http.server
aber unterstützen timeit
).
Mit PEP 338 wurde die -m
Funktionalität erweitert, um <modulename>
Darstellungen in Paketen zu unterstützen. Dies bedeutete Namen, wie http.server
sie jetzt vollständig von unterstützt wurden -m
. Diese Erweiterung bedeutet auch , dass alle Pakete in einem Modulnamen geladen werden mußten (dh die Pakete __init__.py
wurden Dateien ausgeführt), zusammen mit dem Modul selbst, falls die Pakete ihr modifizierten __path__
in __init__.py
.
Ein bemerkenswerter Anwendungsfall, der -m
nach PEP 338 unterstützt wurde, waren absolute Importanweisungen in benutzerdefinierten Paketen, ohne dass ein Paket installiert werden musste sys.path
. Dies kann erreicht werden, indem einfach -m
Skriptdateien aus dem Stammverzeichnis des benutzerdefinierten Projekts geladen werden (da das Stammverzeichnis dann hinzugefügt wird sys.path
).
Die letzte wichtige Funktionserweiterung für -m
kam mit PEP 366 . Mit diesem Update wurde -m
die Möglichkeit gewonnen, nicht nur absolute Importe, sondern auch explizite relative Importe zu unterstützen. Dies wurde erreicht, indem die __package__
Variable für das benannte Modul im -m
Befehl geändert wurde.
Mit all den oben genannten Verbesserungen -m
weist es immer noch ein großes Manko auf. Es können nur Module ausgeführt werden, die in Python (dh *.py
) geschrieben sind. Wenn ein Modulname, der sich auf ein C-kompiliertes Modul bezieht, an -m
den folgenden Fehler übergeben wird , wird der folgende Fehler erzeugt No code object available for <modulename>
.
Vergleich -m
mit anderen Ausführungsmethoden
Im Kern ist das -m
Flag ein Mittel, um Python-Skripte über den Modulnamen und nicht über den Dateinamen auszuführen. Aus diesem Grund vergleichen wir es mit den beiden anderen bekannteren Methoden zur Ausführung von Modulen: (1) Dateiname mit dem python
Befehl und (2) Modulname mit der import
Anweisung.
Auswirkungen der Dateinamenausführung mit dem python
Befehl (dh python <filename>
):
- Pythons wurde
sys.path
so geändert, dass der Speicherort des Moduls in die Importauflösung einbezogen wird
- Die
__name__
Variable des Moduls ist auf gesetzt'__main__'
- Die
__package__
Variable des Moduls ist auf gesetztNone
__init__.py
Für übergeordnete Pakete in werden keine Dateien ausgeführt<filename>
Auswirkungen der Ausführung von Modulnamen mit der import
Anweisung (dh import <modulename>
):
- Python
sys.path
ist nicht für den Import Auflösung in keiner Weise verändert
- Die
__name__
Variable des Moduls wird auf ihren absoluten Modulnamen gesetzt
- Die
__package__
Variable des Moduls wird auf das enthaltende Paket in gesetzt<modulename>
- Alle
__init__.py
Dateien werden für übergeordnete Pakete in ausgeführt<modulename>
Auswirkungen der Ausführung von Modulnamen mit dem -m
Flag (dh python -m <modulename>
):
- Pythons wurde
sys.path
so geändert, dass das aktuelle Verzeichnis in die Importauflösung aufgenommen wird
- Die
__name__
Variable des Moduls ist auf gesetzt'__main__'
- Die
__package__
Variable des Moduls wird auf das enthaltende Paket in gesetzt<modulename>
- Alle
__init__.py
Dateien werden für übergeordnete Pakete in ausgeführt<modulename>
Zusammenfassung
Das -m
Flag ist einfach eine alternative Möglichkeit, ein Python-Skript über den Modulnamen und nicht über den Dateinamen auszuführen. Aus diesem Grund muss man zumindest ein kleines Verständnis dafür haben, wie Python Modulnamen Dateinamen zuordnet, um sie voll ausnutzen zu können. Mit diesem Verständnis erhält man jedoch ein leistungsstarkes neues Tool, das Funktionen von import
Anweisungen (z. B. Unterstützung für explizite relative Importanweisungen) mit der Bequemlichkeit von Befehlszeilenanweisungen kombiniert python
.
-m
zu suchen scheintmymod1
. Beispiel:python -m SimpleHTTPServer
funktioniert, während mitpython SimpleHTTPServer
scheitertcan't open file 'SimpleHTTPServer': [Errno 2] No such file or directory
.