Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Выполнение Python кода через флаг -m
Основная концепция
Команда python -m используется для выполнения модуля как скрипта. При этом Python:
- Находит модуль в
sys.path - Выполняет его содержимое как основную программу (
__name__ == "__main__") - Добавляет текущую директорию в
sys.path
Это отличается от простого вызова python script.py, хотя результаты часто похожи.
Синтаксис и примеры
Базовый синтаксис:
# python -m module_name [args]
# python -m package.submodule [args]
Примеры использования:
# Запуск модуля из стандартной библиотеки
python -m http.server 8000
# Запуск пакета с __main__.py
python -m my_package
# Запуск модуля с аргументами
python -m json.tool input.json
# Запуск pytest
python -m pytest tests/
# Запуск pip
python -m pip install requests
Что происходит при выполнении python -m?
# Представим, что у нас есть модуль: mypackage/mymodule.py
print(f"Module name: {__name__}")
print(f"Module file: {__file__}")
print(f"sys.path[0]: {__import__(sys).path[0]}")
# Запуск через: python -m mypackage.mymodule
# Вывод:
# Module name: __main__
# Module file: /full/path/to/mypackage/mymodule.py
# sys.path[0]: /current/working/directory
# Запуск через: python mypackage/mymodule.py
# Вывод (по сути то же самое!):
# Module name: __main__
# Module file: mypackage/mymodule.py
# sys.path[0]: /current/working/directory
Различия между способами запуска
1. python -m модуль (рекомендуется)
# Файл: mypackage/app.py
import sys
print(f"__name__: {__name__}")
print(f"__package__: {__package__}")
print(f"sys.path[0]: {sys.path[0]}")
# Команда: python -m mypackage.app
# __name__: __main__
# __package__: mypackage
# sys.path[0]: (current directory)
2. python script.py (прямой запуск)
# Команда: python mypackage/app.py
# Проблема: если app.py импортирует из своего пакета
# from . import other_module # ImportError!
# Потому что Python не знает, что это часть пакета
Когда использовать -m?
Сценарий 1: Пакеты с зависимостями от структуры
# mypackage/__main__.py
from . import core
from . import utils
if __name__ == "__main__":
core.run()
# Правильно: python -m mypackage
# Неправильно: python mypackage/__main__.py
Сценарий 2: Использование относительных импортов
# mypackage/handlers/auth.py
from ..utils import validate # Относительный импорт
from ..models import User # Работает только в контексте пакета
# python -m mypackage.handlers.auth ✓ Работает
# python mypackage/handlers/auth.py ✗ ImportError
Сценарий 3: Встроенные модули и утилиты
# Эти команды работают только через -m:
python -m http.server 8000 # Простой веб-сервер
python -m json.tool file.json # Форматирование JSON
python -m venv venv # Создание virtual environment
python -m pip install package # Установка пакетов
python -m pytest # Запуск тестов
Важные различия в sys.path
import sys
def show_path():
print("sys.path:")
for i, path in enumerate(sys.path):
print(f" [{i}] {path}")
# Запуск 1: python -m myapp
# sys.path[0] == (текущая директория)
# Может импортировать из текущей директории
# Запуск 2: python /path/to/script.py
# sys.path[0] == /path/to (директория скрипта)
# Может импортировать только из директории скрипта
Практический пример: правильная структура пакета
# project/
# ├── myapp/
# │ ├── __init__.py
# │ ├── __main__.py # Точка входа
# │ ├── core.py
# │ └── utils.py
# └── setup.py
# myapp/__main__.py
from . import core
import sys
if __name__ == "__main__":
print(f"Запущено как: python -m myapp")
print(f"Текущий пакет: {__package__}")
core.main()
# myapp/core.py
from . import utils
def main():
result = utils.process()
print(f"Result: {result}")
# Запуск:
# $ cd project
# $ python -m myapp ✓ Правильно
# $ python myapp/__main__.py ✗ Неправильно
Ошибки, которые возникают
# Ошибка 1: ImportError при прямом запуске
# python myapp/core.py
# from . import utils # ModuleNotFoundError: __package__ is None
# Решение: python -m myapp.core
# Ошибка 2: Различные sys.path
# Может привести к импорту разных версий модулей
# Ошибка 3: __name__ != __main__
# if __name__ == __main__: # Не выполнится, если модуль импортирован
Выводы
- python -m находит и выполняет модуль через систему импорта Python
- Правильный выбор между
-mи прямым запуском зависит от структуры проекта - Используй -m для пакетов с относительными импортами
- Используй -m для встроенных утилит (http.server, pytest, pip)
- package содержит имя пакета при использовании -m
- sys.path[0] при -m указывает на текущую директорию, что часто более предсказуемо
- Best practice: используй
python -m package_nameвместо прямого запуска скриптов для больших проектов