Команда python -m: выполнение любого модуля Python

Раздел: Прочее -> Команды Python

Обзор команды python -m

Запуск модуля как скрипта с помощью ключа -m позволяет выполнить любой модуль, доступный в интерпретаторе, без указания полного пути к файлу. Это особенно полезно для встроенных модулей, пакетов и собственных утилит.

Основной способ: python -m module_name [аргументы]. Интерпретатор находит модуль module_name в sys.path и запускает его как основной скрипт. Для большинства стандартных модулей это даёт доступ к их интерфейсам командной строки.

python -m http.server 8000

Python run module (запуск модуля как скрипта (python -m))

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Другой пример - создание виртуального окружения:

python -m venv myenv
(папка myenv создана)

Этот подход гарантирует, что модуль выполняется в контексте текущего интерпретатора, избегая проблем с разными версиями Python или относительными импортами.

Как запустить собственный модуль как скрипт?

Создайте файл mymodule.py с блоком if __name__ == "__main__":

# mymodule.py
import sys

def main():
    print("Запущен модуль")
    print(f"Аргументы: {sys.argv[1:]}")

if __name__ == "__main__":
    main()

Запуск:

python -m mymodule arg1 arg2
Запущен модуль
Аргументы: ['arg1', 'arg2']

Ошибка: ModuleNotFoundError: No module named 'mymodule'

Модуль должен быть доступен в sys.path. Если он находится не в текущей директории, добавьте путь в переменную PYTHONPATH или используйте -m из папки с модулем. Или установите модуль (например, с помощью pip install -e .).

В чем различие между python -m и python script.py?

Команда python -m script ищет модуль script (файл script.py) через sys.path, тогда как python script.py запускает файл напрямую. Первый вариант корректно настраивает __package__ и позволяет выполнять пакеты. Рекомендуется для библиотек и утилит, вызываемых из разных мест.

# package_example/__init__.py (пустой)
# package_example/__main__.py
print("Пакет запущен как скрипт")
python -m package_example
Пакет запущен как скрипт

Без -m пришлось бы писать python package_example/__main__.py, что неудобно для распространения.

Как передать аргументы в модуль?

Аргументы указываются после имени модуля. Внутри модуля они доступны через sys.argv.

python -m timeit -n 100 -s "a=1" "a*2"
100 loops, best of 5: 20.2 nsec per loop

Многие модули (например, http.server, unittest, json.tool) принимают дополнительные опции.

Ошибка: unparsed arguments или неправильный синтаксис

Модуль может ожидать определённый порядок или типы аргументов. Проверьте справку модуля: python -m module --help. Например, для http.server порт передаётся числом, а для json.tool - файл.

Как запустить пакет как скрипт?

Для пакета требуется файл __main__.py внутри него. При запуске python -m mypackage интерпретатор выполнит mypackage/__main__.py.

# mypackage/__main__.py
from . import some_function
some_function()
python -m mypackage

Это стандартный способ сделать пакет исполняемым (например, pip - это пакет с __main__.py).

Проблема: импорты внутри пакета

В __main__.py лучше использовать относительные импорты (from . import ...), иначе могут возникнуть ошибки при запуске напрямую. При запуске через -m пакет распознаётся корректно.

Какие стандартные модули часто запускают через -m?

  • http.server - простой HTTP сервер
  • venv - создание виртуальных окружений
  • pip - установка пакетов (хотя предпочтительнее отдельная команда pip)
  • json.tool - форматирование JSON
  • unittest - запуск тестов (python -m unittest discover)
  • pdb - отладчик
  • cProfile - профилирование

Пример с json.tool:

echo '{"a":1,"b":2}' | python -m json.tool
{
    "a": 1,
    "b": 2
}

Как отладить свой модуль?

Запустите модуль под отладчиком:

python -m pdb -m mymodule

Сначала -m передаётся pdb, затем -m после pdb загружает целевой модуль. Или используйте python -m pdb mymodule.py (без -m для файла).

Типичные ошибки при использовании -m

  • ModuleNotFoundError - модуль не найден в sys.path. Решение: проверьте текущую директорию, установите модуль или добавьте путь.
  • AttributeError: module has no attribute '__path__' - попытка запустить обычный модуль как пакет.
  • SystemExit - некоторые модули вызывают sys.exit(), что не является ошибкой, но прерывает выполнение.
  • Проблемы с кодировкой - на Windows могут возникать проблемы с Unicode. Используйте PYTHONIOENCODING=utf-8.

Решения: всегда устанавливайте PYTHONPATH, если модули находятся вне стандартных путей. Для проверки путей выполните python -c "import sys; print(sys.path)".

Заключение

Команда python -m - мощный инструмент для запуска модулей без привязки к их файловому расположению. Она широко используется в скриптах автоматизации, тестировании и при работе с пакетами. Понимание её работы помогает избежать типичных ошибок импорта и улучшает переносимость кода.

Расширенные примеры использования python -m

1. Запуск http.server с кастомной директорией и опциями

Модуль http.server поддерживает аргументы командной строки. Пример запуска сервера на порту 8080, обслуживающего папку ./public:

Пример
python -m http.server 8080 --directory ./public
Serving HTTP on :: port 8080 (http://[::]:8080/) ...

Это удобно для быстрого тестирования статического контента.

2. Использование -m с собственным пакетом, содержащим __main__.py и подмодули

Структура пакета:

Пример
mini_tool/
  __init__.py
  __main__.py
  utils.py

Код __main__.py:

Пример
from .utils import parse_args
import sys

def main():
    args = parse_args(sys.argv[1:])
    print(f"Обработаны аргументы: {args}")

if __name__ == "__main__":
    main()

Код utils.py:

Пример
def parse_args(argv):
    return [a.upper() for a in argv]

Запуск:

Пример
python -m mini_tool hello world
Обработаны аргументы: ['HELLO', 'WORLD']

Это демонстрирует, как можно организовать пакет с CLI-интерфейсом.

3. Профилирование кода с помощью cProfile

Запустите профилирование модуля, который выполняет вычисления:

Пример
# slow_code.py
import time

def compute():
    total = 0
    for i in range(1000000):
        total += i
    time.sleep(0.1)
    return total

if __name__ == "__main__":
    result = compute()
    print(f"Result: {result}")
Пример
python -m cProfile slow_code.py
         1000005 function calls in 0.321 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.101    0.101    0.101    0.101 .../slow_code.py:4(compute)
        1    0.220    0.220    0.321    0.321 {built-in method builtins.exec}
        1    0.000    0.000    0.321    0.321 {built-in method builtins.print}
   ...

Для профилирования собственного модуля используйте python -m cProfile -m mymodule.

4. Отладка с pdb в сочетании с -m

Запустите целевой модуль под отладчиком:

Пример
python -m pdb -m http.server

Отладчик остановится перед выполнением модуля. Для пошаговой отладки собственного модуля:

Пример
python -m pdb -m mymodule arg1

После загрузки появится приглашение (Pdb). Можно ставить точки останова (break), просматривать переменные.

5. Запуск unittest с автоматическим обнаружением тестов

Стандартный модуль unittest позволяет запускать тесты из пакета или директории:

Пример
python -m unittest discover -s tests -p "*_test.py"

Пример структуры:

Пример
tests/
  __init__.py
  math_test.py
  string_test.py

Команда найдёт все файлы, соответствующие шаблону, и выполнит их.

Для запуска одного тестового модуля:

Пример
python -m unittest tests.math_test

Или с уровнем детализации:

Пример
python -m unittest -v tests.math_test
test_addition (tests.math_test.TestMath) ... ok
test_subtraction (tests.math_test.TestMath) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

6. Использование -m для модуля, который устанавливает переменные окружения

Создайте модуль env_setup.py:

Пример
import os

def set_vars():
    os.environ["MY_VAR"] = "value"
    print("Окружение настроено")

if __name__ == "__main__":
    set_vars()

Запустите:

Пример
python -m env_setup
Окружение настроено

Важно: изменения окружения действуют только в процессе выполнения, дочерние процессы наследуют его.

Заключение

Приведённые примеры показывают гибкость python -m для запуска как стандартных, так и пользовательских модулей. Использование этой команды упрощает разработку утилит, отладку и тестирование.

Запуск модуля как скрипта (python -m) - comments

En
Python run module (python)