Команда python -m: выполнение любого модуля Python
Обзор команды python -m
Запуск модуля как скрипта с помощью ключа -m позволяет выполнить любой модуль, доступный в интерпретаторе, без указания полного пути к файлу. Это особенно полезно для встроенных модулей, пакетов и собственных утилит.
Основной способ: python -m module_name [аргументы]. Интерпретатор находит модуль module_name в sys.path и запускает его как основной скрипт. Для большинства стандартных модулей это даёт доступ к их интерфейсам командной строки.
python -m http.server 8000Python 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- форматирование JSONunittest- запуск тестов (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 для запуска как стандартных, так и пользовательских модулей. Использование этой команды упрощает разработку утилит, отладку и тестирование.