Точка входа в приложении на Python

Раздел: Основы Python -> Структура программы Python

Основной способ: проверка __name__

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

def main():
    print('Запуск программы')

if __name__ == '__main__':
    main()

точка входа python (точка входа в программу python)

Пояснения: переменная __name__ принимает значение '__main__' только для исполняемого файла. Если файл импортирован, __name__ равно имени модуля. Таким образом, код внутри блока if выполняется только при запуске скрипта напрямую.

Типичная ошибка: забыть условие if, что приводит к выполнению кода при импорте. Решение: всегда оборачивать точку входа в проверку __name__.

Как сделать, чтобы программа возвращала код ошибки?

Использование sys.exit(main()) позволяет вернуть код завершения операционной системе. main() должна возвращать 0 при успехе, ненулевое значение при ошибке.

import sys

def main():
    # ...
    return 0

if __name__ == '__main__':
    sys.exit(main())
Проблема: если main() не возвращает целое число, sys.exit может выдать ошибку типа. Решение: возвращать явно int или использовать sys.exit() без аргумента.

Случай использования: когда скрипт вызывается из других скриптов или CI/CD и важен код возврата.

Как передать аргументы командной строки в точку входа?

Модуль argparse позволяет определить аргументы и опции. Функция main() принимает разобранные аргументы.

import argparse

def main(args):
    print(f'Имя: {args.name}')

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--name', required=True)
    args = parser.parse_args()
    main(args)
Ошибка: забыть передать args в main, или использовать sys.argv напрямую без парсинга. Решение: всегда парсить аргументы и передавать их в main.

Случай использования: любые скрипты, требующие пользовательского ввода при запуске.

Как запустить пакет как скрипт (python -m mypackage)?

Размещение файла __main__.py внутри пакета. При запуске python -m выполняется этот файл.

# mypackage/__main__.py
from . import main

if __name__ == '__main__':
    main()

Пояснения: требуется создать структуру пакета с __init__.py и __main__.py. Импорты должны быть относительными.

Проблема: относительные импорты не работают при запуске как скрипта (python mypackage/__main__.py). Решение: всегда использовать python -m mypackage.

Как создать консольную команду после установки пакета?

В setup.py или pyproject.toml определяется entry_points с ключом console_scripts. После установки пакета создается исполняемый файл, вызывающий указанную функцию.

# setup.py
from setuptools import setup

setup(
    name='myapp',
    version='1.0',
    py_modules=['myapp'],
    entry_points={
        'console_scripts': [
            'myapp=myapp:main',
        ],
    },
)

Пояснения: функция main должна быть определена в модуле myapp.py. После pip install . в системе появится команда myapp.

Типичная ошибка: опечатка в имени функции или модуля, или забытое if __name__ внутри модуля. Решение: проверять установку и импорт.

Как обработать ошибки на уровне точки входа?

Обернуть вызов main() в try/except, чтобы корректно завершить программу и вывести сообщение об ошибке.

import sys

def main():
    raise RuntimeError('Что-то пошло не так')

if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        print(f'Ошибка: {e}', file=sys.stderr)
        sys.exit(1)
Проблема: перехватываются все исключения, что может скрыть ошибки программирования. Решение: ловить только ожидаемые исключения.

Как упростить создание CLI с множеством команд?

Библиотека click предоставляет декораторы для создания многоуровневых команд.

import click

@click.command()
@click.option('--name', prompt='Ваше имя')
def main(name):
    click.echo(f'Привет, {name}!')

if __name__ == '__main__':
    main()

Пояснения: click автоматически генерирует help, парсит аргументы и обрабатывает ошибки.

Проблема: click нужно устанавливать отдельно. Решение: использовать встроенный argparse для простых случаев.

Расширенные примеры точки входа

Пример 1: Демонстрация разницы между запуском и импортом

Файл mymodule.py:

Пример
print('Этот код выполняется при импорте')

def main():
    print('Функция main выполняется только при прямом запуске')

if __name__ == '__main__':
    main()

Результат при запуске python mymodule.py:

Этот код выполняется при импорте
Функция main выполняется только при прямом запуске

При импорте import mymodule:

Этот код выполняется при импорте

Как видно, функция main не была вызвана.

Пример 2: Скрипт с аргументами через argparse

Пример
import argparse

def main(name, greeting):
    print(f'{greeting}, {name}!')

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Приветствие пользователя')
    parser.add_argument('name', help='Имя пользователя')
    parser.add_argument('--greeting', default='Привет', help='Приветственная фраза')
    args = parser.parse_args()
    main(args.name, args.greeting)

Запуск: python greet.py Иван --greeting Здравствуй

Здравствуй, Иван!

Без --greeting: python greet.py Петр

Привет, Петр!

Пример 3: Пакет с __main__.py

Структура:

Пример
mypackage/__init__.py (пустой)
mypackage/__main__.py
mypackage/core.py

core.py:

Пример
def run():
    print('Пакет mypackage запущен')

__main__.py:

Пример
from .core import run

if __name__ == '__main__':
    run()

Запуск: python -m mypackage

Пакет mypackage запущен

Пример 4: Использование click для CLI

Пример
import click

@click.group()
def cli():
    pass

@cli.command()
@click.option('--count', default=1, help='Количество повторений')
def hello(count):
    for _ in range(count):
        click.echo('Hello!')

if __name__ == '__main__':
    cli()

Запуск: python cli.py hello --count 3

Hello!
Hello!
Hello!

Пример 5: Точка входа через entry_points в setup.py

Создаем файл myapp.py:

Пример
def main():
    print('MyApp запущен')

if __name__ == '__main__':
    main()

setup.py:

Пример
from setuptools import setup

setup(
    name='myapp',
    version='0.1',
    py_modules=['myapp'],
    entry_points={
        'console_scripts': [
            'myapp=myapp:main',
        ],
    },
)

Установка: pip install .

Запуск: myapp

MyApp запущен

После этого команда myapp становится доступной в системе.

точка входа в программу Python - comments

En
точка входа python (python)