Несмотря на то, что на этот вопрос задавали и отвечали несколько раз (например, здесь , здесь , здесь и здесь ), по моему мнению, ни один из существующих ответов полностью или кратко не отражает все значения -m
флага. Поэтому следующее попытается улучшить то, что было раньше.
Введение (TLDR)
Команда -m
делает много вещей, не все из них обязательно будут нужны постоянно. Вкратце: (1) позволяет выполнять сценарии Python с помощью modulename, а не имени файла (2) позволяет выбрать каталог для добавления sys.path
для import
разрешения и (3) позволяет выполнять сценарии Python с относительным импортом из командной строки. ,
прелиминарии
Чтобы объяснить -m
флаг, мы сначала должны прояснить немного терминологии.
Во-первых, основная организационная единица Python называется модулем . Модуль поставляется в одном из двух вариантов: программные модули и модули пакетов. Модуль кода - это любой файл, который содержит исполняемый код Python. Модуль пакета - это каталог, который содержит другие модули (модули кода или модули пакета). Наиболее распространенным типом модулей кода являются *.py
файлы, а наиболее распространенным типом модулей пакета являются каталоги, содержащие __init__.py
файл.
Во-вторых, все модули могут быть однозначно идентифицированы двумя различными способами: <modulename>
и <filename>
. Модули чаще всего идентифицируются по имени модуля в коде Python (например, import <modulename>
) и по имени файла в командной строке (например, python <filename>
). Все интерпретаторы Python могут преобразовывать имена модулей в имена файлов с помощью набора четко определенных правил. Эти правила зависят от sys.path
переменной, и, следовательно, отображение можно изменить, изменив это значение (подробнее о том, как это делается, см. PEP 302 ).
В-третьих, все модули (как код, так и пакет) могут быть выполнены (что означает, что код, связанный с модулем, будет оцениваться интерпретатором Python). В зависимости от метода выполнения и типа модуля, какой код оценивается и когда, может немного измениться. Например, если кто-то выполняет модуль пакета через, python <filename>
тогда <filename>/__init__.py
будет произведена оценка с последующим <filename>/__main__.py
. С другой стороны, если один из них выполняет тот же модуль пакета, import <modulename>
то __init__.py
будут выполняться только пакеты .
Историческое развитие -m
Флаг -m впервые появился в Python 2.4.1 . Первоначально его единственная цель состояла в том, чтобы предоставить альтернативные средства идентификации модуля Python для выполнения. То есть, если бы мы знали <filename>
и <modulename>
модуль, и следующие две команды были эквивалентны: python <filename> <args>
и python -m <modulename> <args>
. Кроме того, согласно PEP 338 эта итерация -m
работала только с модулями верхнего уровня (то есть с модулями, которые можно было найти непосредственно в sys.path без каких-либо промежуточных пакетов).
С завершением PEP 338-m
функциональность была расширена для поддержки <modulename>
представлений за пределами верхних modulenames уровня. Это означало, что имена http.server
были полностью поддержаны. Это усовершенствование также означало, что все пакеты в модуле теперь были загружены (то есть все __init__.py
файлы пакетов были оценены) вместе с самим модулем.
Финальное усовершенствование основных функций -m
появилось в PEP 366 . Благодаря этому обновлению -m
появилась возможность поддерживать не только абсолютный импорт, но и явный относительный импорт. Это было достигнуто путем изменения __package__
переменной для указанного модуля в -m
команде.
Случаи использования
Есть два известных варианта использования флага -m:
Выполнять модули из командной строки, для которых может не быть известно их имя файла. Этот вариант использования использует тот факт, что интерпретатор Python знает, как преобразовать имена модулей в имена файлов. Это особенно полезно, когда требуется запустить модули stdlib или сторонний модуль из командной строки. Например, очень немногие люди знают имя файла для http.server
модуля, но большинство людей знают его имя по модулю, поэтому мы можем выполнить его из командной строки, используя python -m http.server
.
Для выполнения локального пакета, содержащего абсолютный импорт, без необходимости его установки. Этот вариант использования подробно описан в PEP 338 и использует тот факт, что текущий рабочий каталог добавляется, sys.path
а не каталог модуля. Этот вариант использования очень похож на использование pip install -e .
для установки пакета в режиме разработки / редактирования.
Упущения
Со всеми улучшениями, внесенными -m
за эти годы, у него все еще есть один существенный недостаток - он может выполнять только модули кода, написанные на python (то есть * .py). Например, если -m
используется для выполнения модуля скомпилированного кода на C, будет выдана следующая ошибка No code object available for <modulename>
(подробнее см. Здесь ).
Подробные сравнения
Эффекты выполнения модуля с помощью команды python (т.е. python <filename>
):
sys.path
изменен, чтобы включить в <filename>
__name__
установлен на '__main__'
__package__
установлен на None
__init__.py
не оценивается ни для какого пакета (включая его собственный для модулей пакета)
__main__.py
оценивается для пакетов модулей; код оценивается для модулей кода.
Эффекты выполнения модуля через оператор импорта (т. Е. import <modulename>
):
sys.path
это не изменены каким - либо образом
__name__
устанавливается в абсолютной форме <modulename>
__package__
устанавливается в непосредственный родительский пакет в <modulename>
__init__.py
оценивается для всех пакетов (включая свой собственный для модулей пакета)
__main__.py
это не оценивается для модулей пакетов; код оценивается для модулей кода
Эффекты выполнения модуля через флаг -m (т. Е. python -m <modulename>
):
sys.path
изменен, чтобы включить текущий каталог
__name__
установлен на '__main__'
__package__
устанавливается в непосредственный родительский пакет в <modulename>
__init__.py
оценивается для всех пакетов (включая свой собственный для модулей пакета)
__main__.py
оценивается для пакетов модулей; код оценивается для модулей кода
Вывод
-m
Флаг, в самом простом, средство для выполнения питона сценариев из командной строки с помощью modulenames , а не имена файлов. Кроме того, -m
предоставляет дополнительные функциональные возможности, сочетающие мощь import
операторов (например, поддержку явного относительного импорта и автоматическую __init__
оценку пакетов ) с удобством командной строки python.
-m
кажется, поискmymod1
в пути по умолчанию библиотеки. Пример:python -m SimpleHTTPServer
работает, аpython SimpleHTTPServer
не сcan't open file 'SimpleHTTPServer': [Errno 2] No such file or directory
.