Главный модуль Python: __main__
Основные подходы к использованию __main__
Как организовать выполнение кода только при прямом запуске скрипта?
Самое эффективное решение - использование условной конструкции if __name__ == "__main__":. Эта проверка позволяет отделить код, который выполняется при импорте модуля, от кода, который запускается только при вызове файла как основного скрипта.
# mymodule.py
def greet(name):
return f"Привет, {name}!"
if __name__ == "__main__":
print(greet("Мир"))
Python module naming (соглашения об именовании модулей python)
При запуске скрипта python mymodule.py будет выведено "Привет, Мир!". Если же модуль импортировать в другой файл (import mymodule), то функция greet будет доступна, но код внутри блока if не выполнится.
Типичные ошибки:
- Забыть добавить условие - тогда код запускается при любом импорте.
- Опечатки в имени
__main__(два подчёркивания с обеих сторон). - Рекурсивный импорт при наличии в блоке импорта того же модуля.
Как сделать, чтобы код выполнялся только при импорте, а не при запуске?
Иногда нужно, наоборот, выполнять код только при импортировании модуля. Для этого можно проверить if __name__ != "__main__":. Однако такое встречается редко. Чаще используется для инициализации модуля при его загрузке.
# setup.py
print("Модуль загружен")
if __name__ != "__main__":
print("Этот код выполняется при импорте")
Python modules (модули python)
Цель:
Инициализация глобальных переменных или регистрация компонентов при импорте.Как передать аргументы командной строки в основной модуль?
В блоке if __name__ == "__main__": можно вызвать функцию с аргументами из sys.argv или использовать argparse.
# calc.py
import sys
def add(a, b):
return a + b
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Использование: python calc.py число1 число2")
else:
result = add(float(sys.argv[1]), float(sys.argv[2]))
print(f"Результат: {result}")
Python module main (основной модуль __main__)
При запуске python calc.py 5 3 выведет "Результат: 8.0".
Проблема:
Незащищённый доступ кsys.argv может привести к ошибкам при отсутствии аргументов. Рекомендуется использовать argparse.
Как использовать __main__.py в пакете для создания точки входа?
Если модуль представляет собой пакет (директорию с __init__.py), можно добавить файл __main__.py. При запуске пакета через python -m mypackage выполнится код из __main__.py.
# mypackage/__main__.py
def main():
print("Запущен пакет mypackage")
if __name__ == "__main__":
main()
Запуск: python -m mypackage выведет "Запущен пакет mypackage".
Сценарий использования:
Пакеты, которые можно запускать как скрипты, например, для утилит командной строки.Как организовать тестирование внутри модуля при прямом запуске?
В блоке if __name__ == "__main__": можно вызывать тесты, например, с помощью unittest.main() или doctest.testmod().
# test_demo.py
import doctest
def factorial(n):
"""Возвращает факториал числа n.
>>> factorial(5)
120
"""
if n == 0:
return 1
return n * factorial(n-1)
if __name__ == "__main__":
doctest.testmod(verbose=True)
При запуске скрипта будут выполнены doctest-тесты и показан результат.
Расширенные примеры использования __main__
Пример 1: Обработка аргументов с argparse
# greeter.py
import argparse
def greet(name, greeting="Привет"):
return f"{greeting}, {name}!"
def main():
parser = argparse.ArgumentParser(description="Простой приветственный скрипт")
parser.add_argument("name", help="Имя для приветствия")
parser.add_argument("-g", "--greeting", default="Привет", help="Приветствие (по умолчанию 'Привет')")
args = parser.parse_args()
print(greet(args.name, args.greeting))
if __name__ == "__main__":
main()
Запуск:
$ python greeter.py Мир -g Здравствуйте Здравствуйте, Мир!
Пример 2: Пакет с __main__.py и изучением атрибутов модуля
# mypackage/__init__.py
# пустой файл
# mypackage/__main__.py
import sys
def main():
print("Модуль __main__ выполнен")
print("Аргументы:", sys.argv[1:] if len(sys.argv) > 1 else "нет")
print("Значение __name__:", __name__)
if __name__ == "__main__":
main()
Запуск:
$ python -m mypackage --test Модуль __main__ выполнен Аргументы: ['--test'] Значение __name__: __main__
Пример 3: Логирование при запуске
# logger_demo.py
import logging
def setup_logging(level=logging.INFO):
logging.basicConfig(level=level, format="%(asctime)s - %(levelname)s - %(message)s")
def do_work():
logging.info("Выполнение работы")
if __name__ == "__main__":
setup_logging()
do_work()
Результат:
2025-03-27 12:00:00,000 - INFO - Выполнение работы
Пример 4: Встроенное тестирование с unittest
# calculator.py
import unittest
def add(a, b):
return a + b
class TestCalculator(unittest.TestCase):
def test_add(self):
self.assertEqual(add(2, 3), 5)
if __name__ == "__main__":
unittest.main()
Результат:
. ---------------------------------------------------------------------- Ran 1 test in 0.001s OK
Пример 5: Модуль с режимом разработки и продакшн
# config_demo.py
import os
def load_config():
return {"debug": os.getenv("DEBUG", "false").lower() == "true"}
def run():
config = load_config()
if config["debug"]:
print("Режим отладки включен")
else:
print("Продакшн режим")
if __name__ == "__main__":
run()
Запуск с переменной окружения:
$ DEBUG=true python config_demo.py Режим отладки включен