Pomimo tego, że zadawano to pytanie i odpowiadano na nie kilka razy (np. Tutaj , tutaj , tutaj i tutaj ), moim zdaniem żadna istniejąca odpowiedź nie oddaje w pełni ani zwięźle wszystkich implikacji -mflagi. Dlatego poniższe postarają się ulepszyć to, co było wcześniej.
Wprowadzenie (TLDR)
-mKomenda robi wiele rzeczy, nie wszystkie z nich muszą być potrzebne przez cały czas. W skrócie: (1) pozwala na wykonywanie skryptów Pythona za pomocą nazwy modułu zamiast nazwy pliku (2) pozwala wybrać katalog do dodania w sys.pathcelu importrozwiązania problemu oraz (3) umożliwia wykonywanie skryptów Pythona z relatywnymi importami z wiersza poleceń .
Czynności wstępne
Aby wyjaśnić -mflagę, musimy najpierw wyjaśnić trochę terminologii.
Po pierwsze, podstawowa jednostka organizacyjna Pythona jest nazywana modułem . Moduły występują w jednym z dwóch rodzajów: moduły kodu i moduły pakietów. Moduł kodu to dowolny plik zawierający kod wykonywalny w języku Python. Moduł pakietu to katalog zawierający inne moduły (moduły kodu lub moduły pakietów). Najpopularniejszym typem modułów kodu są *.pypliki, podczas gdy najpopularniejszym typem modułów pakietu są katalogi zawierające __init__.pyplik.
Po drugie, wszystkie moduły można jednoznacznie zidentyfikować na dwa różne sposoby: <modulename>i <filename>. Moduły są najczęściej identyfikowane przez nazwę modułu w kodzie Pythona (np. import <modulename>) I nazwę pliku w wierszu poleceń (np python <filename>.). Wszystkie interpretery Pythona mogą konwertować nazwy modulów na nazwy plików za pomocą zestawu dobrze zdefiniowanych reguł. Reguły te zależą od sys.pathzmiennej i dlatego mapowanie można zmienić, zmieniając tę wartość (więcej informacji na temat tego, jak to się robi, znajduje się w PEP 302 ).
Po trzecie, wszystkie moduły (zarówno kod, jak i pakiet) mogą zostać wykonane (przez co rozumiemy kod powiązany z modułem zostanie oceniony przez interpreter Pythona). W zależności od metody wykonania i typu modułu, jaki kod jest oceniany i kiedy, może się nieco zmienić. Na przykład, jeśli wykonuje się moduł pakietu za pośrednictwem, python <filename>to <filename>/__init__.pyzostanie ocenione, a po nim <filename>/__main__.py. Z drugiej strony, jeśli ktoś wykonuje ten sam moduł pakietu za pośrednictwem, import <modulename>to tylko pakiety __init__.pyzostaną wykonane.
Rozwój historyczny -m
Flaga -m została po raz pierwszy wprowadzona w Pythonie 2.4.1 . Początkowo jego jedynym celem było zapewnienie alternatywnych sposobów identyfikacji modułu Pythona do wykonania. Oznacza to, że gdybyśmy znali zarówno moduł, jak <filename>i <modulename>dla modułu, następujące dwa polecenia byłyby równoważne: python <filename> <args>i python -m <modulename> <args>. Ponadto, zgodnie z PEP 338, ta iteracja -mdziałała tylko z nazwami modulów najwyższego poziomu (tj. Modułami, które można znaleźć bezpośrednio w sys.path bez żadnych pakietów pośredniczących).
Wraz z zakończeniem PEP 338-m funkcjonalność została rozszerzona na wsparcie <modulename>reprezentacji poza najlepszych moduleNames szczebla. Oznaczało to, że nazwy takie jak http.serverbyły teraz w pełni obsługiwane. To ulepszenie oznaczało również, że wszystkie pakiety w module zostały załadowane (tj. Wszystkie __init__.pypliki pakietów zostały ocenione) wraz z samym modułem.
Ostatnie główne ulepszenie funkcji -mprzyszło wraz z PEP 366 . Dzięki tej aktualizacji -mzyskał możliwość obsługi nie tylko importu bezwzględnego, ale także jawnego importu względnego. Osiągnięto to poprzez zmodyfikowanie __package__zmiennej dla nazwanego modułu w -mpoleceniu.
Przypadków użycia
Istnieją dwa godne uwagi przypadki użycia flagi -m:
Aby uruchomić moduły z wiersza poleceń, dla których można nie znać ich nazw plików. Ten przypadek użycia wykorzystuje fakt, że interpreter Pythona wie, jak przekonwertować nazwy modulów na nazwy plików. Jest to szczególnie korzystne, gdy chce się uruchomić moduły stdlib lub moduł innej firmy z wiersza poleceń. Na przykład, bardzo niewiele osób zna nazwę pliku http.servermodułu, ale większość ludzi zna jego nazwę modułu, więc możemy go uruchomić z wiersza poleceń za pomocą python -m http.server.
Aby wykonać lokalny pakiet zawierający bezwzględne importy bez konieczności instalowania go. Ten przypadek użycia jest szczegółowo opisany w PEP 338 i wykorzystuje fakt, że bieżący katalog roboczy jest dodawany do sys.pathkatalogu modułu, a nie do niego. Ten przypadek użycia jest bardzo podobny do używania pip install -e .do instalowania pakietu w trybie tworzenia / edycji.
Niedociągnięcia
Pomimo wszystkich ulepszeń wprowadzonych na -mprzestrzeni lat, nadal ma jedną poważną wadę - może wykonywać tylko moduły kodu napisane w Pythonie (tj. * .Py). Na przykład, jeśli -mjest używany do wykonania skompilowanego modułu kodu w C, zostanie wygenerowany następujący błąd No code object available for <modulename>(zobacz tutaj, aby uzyskać więcej informacji).
Szczegółowe porównania
Efekty wykonania modułu za pomocą polecenia Pythona (tj. python <filename>):
sys.path jest modyfikowany, aby uwzględnić ostateczny katalog w <filename>
__name__ jest ustawione na '__main__'
__package__ jest ustawione na None
__init__.py nie jest oceniany dla żadnego pakietu (w tym własnego dla modułów pakietu)
__main__.pyjest oceniany dla modułów pakietu; kod jest oceniany pod kątem modułów kodu.
Efekty wykonania modułu poprzez instrukcję importu (tj. import <modulename>):
sys.pathnie jest w żaden sposób modyfikowany
__name__ jest ustawiona na absolutną formę <modulename>
__package__ jest ustawiony na bezpośredni pakiet nadrzędny w <modulename>
__init__.py jest oceniany dla wszystkich pakietów (w tym własnego dla modułów pakietów)
__main__.pynie jest oceniany dla modułów pakietu; kod jest oceniany pod kątem modułów kodu
Efekty wykonania modułu za pomocą flagi -m (tj. python -m <modulename>):
sys.path jest modyfikowany w celu uwzględnienia bieżącego katalogu
__name__ jest ustawione na '__main__'
__package__ jest ustawiony na bezpośredni pakiet nadrzędny w <modulename>
__init__.py jest oceniany dla wszystkich pakietów (w tym własnego dla modułów pakietów)
__main__.pyjest oceniany dla modułów pakietu; kod jest oceniany pod kątem modułów kodu
Wniosek
-mFlaga jest w swej najprostszej, środki do wykonywania skryptów Pythona z linii poleceń za pomocą moduleNames zamiast nazw plików. Dodatkowo -mzapewnia dodatkową funkcjonalność, która łączy moc importinstrukcji (np. Obsługę jawnych importów względnych i automatycznej __init__oceny pakietów ) z wygodą wiersza poleceń Pythona.
-mwydaje się, że wyszukujęmymod1w domyślnej ścieżce biblioteki. Przykład:python -m SimpleHTTPServerdziała, alepython SimpleHTTPServerkończy się niepowodzeniem zcan't open file 'SimpleHTTPServer': [Errno 2] No such file or directory.