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 -mFlagge vollständig oder präzise . Daher wird im Folgenden versucht, das bisherige zu verbessern.
TLDR
Der -mBefehl 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.pathzur importAuflö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 -mFlagge 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, *.pyDateien, 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.patheine 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 -mkann 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 -mder hinzugefügt wurde, wurden lediglich Module von gesucht und ausgeführt <modulename>(wobei zusätzlich das aktuelle Verzeichnis hinzugefügt wurde, sys.pathdamit auch lokale Module gefunden werden konnten). Gemäß PEP 338 wurde auch die ursprüngliche Implementierung eingeschränkt, so dass -mkeine Modulnamen in Paketen referenziert werden konnten (dh die Version 2.4.1 würde den Modulnamen nicht unterstützen, http.serveraber unterstützen timeit).
Mit PEP 338 wurde die -mFunktionalität erweitert, um <modulename>Darstellungen in Paketen zu unterstützen. Dies bedeutete Namen, wie http.serversie 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__.pywurden Dateien ausgeführt), zusammen mit dem Modul selbst, falls die Pakete ihr modifizierten __path__in __init__.py.
Ein bemerkenswerter Anwendungsfall, der -mnach 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 -mSkriptdateien aus dem Stammverzeichnis des benutzerdefinierten Projekts geladen werden (da das Stammverzeichnis dann hinzugefügt wird sys.path).
Die letzte wichtige Funktionserweiterung für -mkam mit PEP 366 . Mit diesem Update wurde -mdie 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 -mBefehl geändert wurde.
Mit all den oben genannten Verbesserungen -mweist 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 -mden folgenden Fehler übergeben wird , wird der folgende Fehler erzeugt No code object available for <modulename>.
Vergleich -mmit anderen Ausführungsmethoden
Im Kern ist das -mFlag 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 pythonBefehl und (2) Modulname mit der importAnweisung.
Auswirkungen der Dateinamenausführung mit dem pythonBefehl (dh python <filename>):
- Pythons wurde
sys.pathso 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__.pyFür übergeordnete Pakete in werden keine Dateien ausgeführt<filename>
Auswirkungen der Ausführung von Modulnamen mit der importAnweisung (dh import <modulename>):
- Python
sys.pathist 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__.pyDateien werden für übergeordnete Pakete in ausgeführt<modulename>
Auswirkungen der Ausführung von Modulnamen mit dem -mFlag (dh python -m <modulename>):
- Pythons wurde
sys.pathso 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__.pyDateien werden für übergeordnete Pakete in ausgeführt<modulename>
Zusammenfassung
Das -mFlag 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 importAnweisungen (z. B. Unterstützung für explizite relative Importanweisungen) mit der Bequemlichkeit von Befehlszeilenanweisungen kombiniert python.
-mzu suchen scheintmymod1. Beispiel:python -m SimpleHTTPServerfunktioniert, während mitpython SimpleHTTPServerscheitertcan't open file 'SimpleHTTPServer': [Errno 2] No such file or directory.