Точка входа в приложении на Python
Основной способ: проверка __name__
Цель: обеспечить выполнение определенного блока кода только при прямом запуске скрипта, а не при его импорте. Это стандартная практика для создания модульных программ.
def main():
print('Запуск программы')
if __name__ == '__main__':
main()точка входа python (точка входа в программу python)
Пояснения: переменная __name__ принимает значение '__main__' только для исполняемого файла. Если файл импортирован, __name__ равно имени модуля. Таким образом, код внутри блока if выполняется только при запуске скрипта напрямую.
Как сделать, чтобы программа возвращала код ошибки?
Использование sys.exit(main()) позволяет вернуть код завершения операционной системе. main() должна возвращать 0 при успехе, ненулевое значение при ошибке.
import sys
def main():
# ...
return 0
if __name__ == '__main__':
sys.exit(main())Случай использования: когда скрипт вызывается из других скриптов или 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)Случай использования: любые скрипты, требующие пользовательского ввода при запуске.
Как запустить пакет как скрипт (python -m mypackage)?
Размещение файла __main__.py внутри пакета. При запуске python -m выполняется этот файл.
# mypackage/__main__.py
from . import main
if __name__ == '__main__':
main()Пояснения: требуется создать структуру пакета с __init__.py и __main__.py. Импорты должны быть относительными.
Как создать консольную команду после установки пакета?
В 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.
Как обработать ошибки на уровне точки входа?
Обернуть вызов 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, парсит аргументы и обрабатывает ошибки.
Расширенные примеры точки входа
Пример 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.pycore.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 становится доступной в системе.