Незважаючи на запитання та відповіді на це кілька разів (наприклад, тут , тут , тут , і тут ), на мою думку, жодна з існуючих відповідей повністю чи стисло не відображає всіх наслідків -m
прапора. Тому далі буде намагатися покращити те, що було раніше.
Вступ (TLDR)
-m
Команда робить багато речей , не всі з них обов'язково будуть потрібні весь час. Коротше кажучи: (1) дозволяє пітон, щоб скрипти виконувалися з допомогою MODULENAME , а не ім'я файлу (2) дозволяє вибрати каталог , щоб додати до sys.path
для import
дозволу і (3) дозволяє пітон сценарії з відносно імпорту повинні бути виконані з командного рядка .
Прелімінарії
Щоб пояснити -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
.