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

Введение __name__ и __main__ на примерах

Я считаю, что вы когда-нибудь видели if __name__ == '__main__' в каком-нибудь репозитории, приложении или библиотеках исходного кода Python. Вы можете знать, а можете и не знать, что это, потому что вам это определенно не понадобится, если вы типичный специалист по обработке данных, который большую часть времени использует Jupyter Notebook. Или вы можете просто имитировать использование этого выражения, даже если он не совсем уверен, что он делает, как и я, когда я начал изучать Python :)

В этой статье я расскажу вам, что он делает, как он работает и когда его использовать. Как указано в заголовке, его обычно называют «точкой входа» приложения.

Простой пример - что он делает?

Позвольте мне использовать простой пример, чтобы продемонстрировать, что он делает.

Предположим, мы разрабатываем чрезвычайно простое приложение Python, которое может вычислять площадь фигур. Начнем с круга.

Чтобы вычислить площадь круга, нам нужно значение pi. Конечно, лучший способ получить значение PI - использовать встроенный пакет math.pi. Однако предположим, что мы должны определить это сами.

pi = 3.1415926
def main():
    print('pi is', pi)
main()

Как показано на снимке экрана, я создал модуль с именем if_name_test, а также файл Python с именем mylib.py, который будет использоваться для хранения всех констант.

Здесь определяется значение pi, и я также хочу создать метод main(), который будет использоваться для проверки всех констант и методов. В конце скрипта вызывается метод main() для отображения значения pi.

Теперь давайте запустим файл сценария.

Без проблем. Значение pi печатается, потому что мы запустили основной метод.

Теперь давайте создадим еще один файл Python с именем calculate.py, который будет использоваться для вычисления площадей фигур. Он импортирует постоянное значение pi из mylib. Обратите внимание, что каталог if_name_test создается в рабочем каталоге, поэтому нам нужно импортировать из if_name_test.mylib, а не из .mylib.

from if_name_test.mylib import pi
def get_circle_area(r):
    return r * (pi ** 2)
def main():
    r = int(input('Please input the radius of the circle: '))
    print(f'The area of the circle with radius {r} is: {get_circle_area(r)}')
main()

Здесь мы определяем функцию вычисления площади круга. Затем здесь определяется другой main() метод, чтобы попросить пользователя ввести радиус и вернуть площадь на основе введенных данных.

Посмотрим, что будет счастливым, если мы запустим файл сценария.

Все нормально, кроме значения pi было напечатано. Мы никогда не просим напечатать его, как он это сделал? Это потому, что мы импортировали mylib, а метод main() вызывается в конце файла mylib.py.

Здесь нам нужно использовать встроенную переменную __name__. Давайте добавим условие if к main() методу в mylib.py.

if __name__ == '__main__':
    main()

Если вы, как и я, используете PyCharm, вы можете заметить зеленую кнопку воспроизведения в только что добавленном условии if. PyCharm распознает «точку входа», поэтому он добавляет этот ярлык для запуска сценария за нас. Если мы запустим файл, значение pi по-прежнему будет выводиться как обычно.

Однако, если мы вернемся к calculation.py файлу и запустим его, значение pi больше не будет печататься.

Нам не нужно изменять calculation.py, просто добавив условие if в наш файл lib и сделаем трюк.

Как это работает?

Я не буду копировать слова из официальной документации, как это делается в большинстве руководств, потому что вы всегда можете сделать это самостоятельно. Вместо этого я продемонстрирую это на примерах.

Фактически, условие if работает, потому что

  • Когда мы запускаем файл mylib.py, __name__ равно '__main__'
  • Когда мы импортируем файл mylib.py из calculation.py, он не должен быть '__main__', чтобы метод main() не был вызван.

Давайте проверим это, распечатав __name__ переменных в обоих файлах.

В mylib.py мы добавляем

print(f'In mylib.py, the __name__ variable is {__name__}')

В calculation.py мы добавляем

print(f'In calculation.py, the __name__ variable is {__name__}')

Советы: вы также можете использовать переменную __file__ для получения имени файла, а не вводить их вручную :)

Теперь давайте запустим файл calculation.py.

OK. Переменной __name__ будет присвоено значение __main__ из файла, который мы запускаем. В этом случае файл mylib.py не является отправной точкой, а импортируется как модуль, ему присваивается имя модуля. Следовательно, метод main() в mylib.py не будет вызываться.

Что ж, я мог бы остановиться на этом, поскольку я использовал этот пример, чтобы продемонстрировать, как работает переменная __name__. Однако я хотел бы показать еще один пример, потому что меня действительно смутил метод main() и значение __name__ переменной '__main__', когда я это узнал.

Имеет смысл использовать main() в качестве имени метода, потому что большая часть другого языка может быть обязательной для использования имени в качестве точки входа. Однако изучающий Python может подумать, что значение переменной __name__ равно '__main__', потому что мы определили метод main().

Это совершенно неважно!

Давайте изменим имя метода в mylib.py с main() на my_constants(). Конечно, внутри условия if нам нужно вызвать метод, который был переименован.

pi = 3.1415926
def my_constants():
    print('pi is', pi)
if __name__ == '__main__':
    my_constants()

И давайте снова запустим файл.

Совершенно никаких проблем. Так что пусть вас не смущает такое количество main :)

Когда это использовать?

Как упоминалось выше, вы, вероятно, никогда не будете использовать переменную __name__ в Jupyter Notebooks, если вы типичный специалист по данным. Однако его рекомендуется использовать в любых приложениях Python, которые

Любые файлы, в которых есть что-то, что вы не хотите, чтобы они запускались, если файл не является точкой входа.

Типичным примером будут приложения Flask. Если вы используете / изучаете Python для разработки веб-сервисов с помощью flask, вы, должно быть, видели, что метод app.run() вызывается внутри условия if-name.

По сути, метод app.run() будет вызываться при запуске основного файла Flask для тестирования конечных точек API в среде разработки. Однако, как правило, не рекомендуется запускать приложения Flask напрямую с использованием Python в производственной среде. Вместо этого мы используем Nginx + uWSGI для запуска запускаемых веб-служб по многим причинам, например в целях мониторинга. В этом случае app.run() в файле сценария Python больше не будет точкой входа. Чтобы предотвратить его запуск на месте, мы должны поместить его в условие if-name.

Резюме

В этой статье я представил использование переменной __name__ в условии «if-name», чтобы проверить, является ли текущий файл точкой входа приложения Python, проверяя, равен ли он '__main__'.

Кроме того, я продемонстрировал, как работает переменная __name__, и показал некоторые моменты, которые легко запутать.

Наконец, Flask используется в качестве примера, чтобы показать, когда использовать условие «if-name». Очень важно понимать, как это работает и когда мы должны его использовать, чтобы разработать надежное приложение Python.

Жизнь коротка, используйте Python!