Ausführung von Python-Code mit der Option -m oder nicht
Verwenden Sie die -m
Flagge.
Die Ergebnisse sind nahezu identisch, wenn Sie ein Skript haben. Wenn Sie jedoch ein Paket ohne -m
Flag entwickeln, können die Importe nicht ordnungsgemäß ausgeführt werden, wenn Sie ein Unterpaket oder Modul im Paket als Haupteintrag ausführen möchten Zeigen Sie auf Ihr Programm (und glauben Sie mir, ich habe es versucht.)
Die Dokumente
Wie die Dokumente auf der Flagge -m sagen:
Durchsuchen Sie sys.path nach dem benannten Modul und führen Sie dessen Inhalt als __main__
Modul aus.
und
Wie bei der Option -c wird das aktuelle Verzeichnis am Anfang von sys.path hinzugefügt.
so
python -m pdb
ist ungefähr gleichbedeutend mit
python /usr/lib/python3.5/pdb.py
(vorausgesetzt, Sie haben kein Paket oder Skript in Ihrem aktuellen Verzeichnis namens pdb.py)
Erläuterung:
Das Verhalten wird "absichtlich ähnlich" zu Skripten gemacht.
Viele Standardbibliotheksmodule enthalten Code, der bei ihrer Ausführung als Skript aufgerufen wird. Ein Beispiel ist das Timeit-Modul:
Einige Python-Codes sollen als Modul ausgeführt werden: (Ich denke, dieses Beispiel ist besser als das Beispiel für die Befehlszeilenoption doc)
$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop
$ python -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 3: 33.4 usec per loop
$ python -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 3: 25.2 usec per loop
Und aus den Highlights der Versionshinweise für Python 2.4 :
Die Befehlszeilenoption -m - python -m modulename findet ein Modul in der Standardbibliothek und ruft es auf. Zum Beispiel python -m pdb
ist äquivalent zupython /usr/lib/python2.4/pdb.py
Zusatzfrage
In der Python Essential Reference von David Beazley wird dies außerdem als "Die Option -m führt ein Bibliotheksmodul als Skript aus, das __main__
vor der Ausführung des Hauptskripts innerhalb des Moduls ausgeführt wird".
Dies bedeutet, dass jedes Modul, das Sie mit einer Importanweisung nachschlagen können, als Einstiegspunkt des Programms ausgeführt werden kann - wenn es einen Codeblock hat, normalerweise gegen Ende, mit if __name__ == '__main__':
.
-m
ohne das aktuelle Verzeichnis zum Pfad hinzuzufügen:
Ein Kommentar hier an anderer Stelle sagt:
Dass die Option -m auch das aktuelle Verzeichnis zu sys.path hinzufügt, ist offensichtlich ein Sicherheitsproblem (siehe: Preload-Angriff). Dieses Verhalten ähnelt der Suchreihenfolge für Bibliotheken in Windows (bevor es kürzlich gehärtet wurde). Es ist schade, dass Python nicht dem Trend folgt und keine einfache Möglichkeit bietet, das Hinzufügen zu deaktivieren. zu sys.path
Nun, dies zeigt das mögliche Problem - (in Windows entfernen Sie die Anführungszeichen):
echo "import sys; print(sys.version)" > pdb.py
python -m pdb
3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]
Verwenden Sie das -I
Flag, um dies für Produktionsumgebungen zu sperren (neu in Version 3.4):
python -Im pdb
usage: pdb.py [-c command] ... pyfile [arg] ...
etc...
aus den Dokumenten :
-I
Führen Sie Python im isolierten Modus aus. Dies impliziert auch -E und -s. Im isolierten Modus enthält sys.path weder das Verzeichnis des Skripts noch das Site-Packages-Verzeichnis des Benutzers. Alle PYTHON * -Umgebungsvariablen werden ebenfalls ignoriert. Weitere Einschränkungen können auferlegt werden, um zu verhindern, dass der Benutzer schädlichen Code einfügt.
Was macht __package__
das
Es ermöglicht explizite relative Importe, die für diese Frage jedoch nicht besonders wichtig sind - siehe diese Antwort hier: Was ist der Zweck des Attributs "__package__" in Python?
PYTHONPATH=test python -m foo.bar
? Könnten Sie es bitte im Detail erklären?