Вступление
Часто можно увидеть, есть if __name__ == "__main__"
в скриптах Python,
которые мы находим в Интернете, или в одном из многих, которые мы пишем
сами.
Почему мы используем этот оператор if при запуске наших программ Python? В этой статье мы объясним механику его использования, преимущества и где это можно использовать.
Атрибут __name__ и область действия __main__
__name__
по умолчанию является одним из имен в текущей локальной
области . Интерпретатор Python автоматически добавляет это значение,
когда мы запускаем скрипт Python или импортируем наш код как модуль.
Попробуйте выполнить следующую команду в своем интерпретаторе Python. Вы
можете узнать, что __name__
принадлежит к списку атрибутов в dir()
:
dir()
{.ezlazyload}
__name__
в Python - это специальная переменная, которая определяет имя
класса, текущего модуля или скрипта, из которого он вызывается.
Создайте новую папку с именем name_scripts
чтобы мы могли написать
несколько скриптов, чтобы понять, как все это работает. В этой папке
создайте новый файл script1.py
со следующим кодом:
print(f'The __name__ from script1 is "{__name__}"')
{.ezlazyload}
Это круто! Мы ожидаем, что имя нашего файла script1
Что означает вывод
__main__
?
По умолчанию, когда сценарий выполняется, интерпретатор читает сценарий
и присваивает строку __main__
ключевому слову __name__
Это становится еще более интересным, когда приведенный выше сценарий
импортируется в другой сценарий. Рассмотрим файл Python с именем
script2.py
со следующим кодом:
import script1 # The print statement gets executed upon import
print(f'The __name__ from script2 is "{__name__}"')
{.ezlazyload}
Как вы можете видеть, когда сценарий выполняется, вывод выдается как
script1
обозначающий имя сценария. Последний оператор печати находится
в области действия script2
и когда он запускается, вывод печатается
как __main__
.
Теперь, когда мы понимаем, как Python использует __name__
и когда она
дает ей значение «__main__», давайте посмотрим, почему мы проверяем
ее значение перед выполнением кода.
if __name__ == "__main__" в действии
Мы используем оператор if для запуска блоков кода, только если наша программа является основной выполняемой программой. Это позволяет нашей программе быть исполняемой сама по себе, но удобной для других модулей Python, которые могут захотеть импортировать некоторые функции без необходимости запускать код.
Рассмотрим следующие программы Python:
а) script3.py
содержит функцию с именем add()
которая вызывается
только из основного контекста.
def add(a, b):
return a+b
if __name__ == "__main__":
print(add(2, 3))
Вот результат при script3.py
:
{.ezlazyload}
Поскольку сценарий выполнялся напрямую, ключевому слову __name__
__main__
, и выполняется блок кода с условием
if __name__ == "__main__"
б) Вот что происходит, когда этот фрагмент импортируется из script4.py
:
import script3
print(f"{script3.__name__}")
{.ezlazyload}
Блок под if __name__ == "__main__"
из script3.py
не был выполнен,
как ожидалось. Это произошло потому, что __name__
теперь присвоено имя
сценария: script3
. Это можно проверить с помощью данного оператора
print, который печатает присвоенное значение ключевому слову __name__
Как __name__ == "__main__" помогает в разработке?
Вот несколько вариантов использования этого оператора if при создании сценария.
- Тестирование - это хорошая практика, которая помогает не только выявлять ошибки, но и обеспечивать надлежащее поведение вашего кода. Тестовые файлы должны импортировать в них функцию или объект. В этих случаях мы обычно не хотим, чтобы скрипт запускался как основной модуль.
- Вы создаете библиотеку, но хотите включить демонстрацию или другие специальные сценарии выполнения для пользователей. Использование этого оператора if не затрагивает модули Python, которые используют ваш код в качестве библиотеки.
Создание файла __main__.py для модулей
Смысл наличия if __name__ == "__main__"
состоит в том, чтобы получить
фрагмент кода при условии, что он будет выполнен, когда сценарий
находится в области видимости __main__
Однако при создании пакетов на
Python лучше, если код, который будет выполняться в __main__
будет
записан в отдельном файле.
Рассмотрим следующий пример - пакет для выполнения расчетов. Древовидную структуру файлов для такого сценария можно представить в виде:
calc # --> Root directory
├── __main__.py
├── script1.py
├── script2.py
├── script3.py
├── script4.py
└── src # --> Sub-directory
├── add.py
└── sub.py
Древовидная структура содержит calc
в качестве корневого каталога и
подкаталог, известный как src
. __main__.py
в calc
содержит
следующее содержимое:
from src.add import add
from src.sub import sub
a, b = input("Enter two numbers separated by commas: ").split(',')
a, b = int(a), int(b)
print(f"The sum is: {add(a, b)}")
print(f"The difference is: {sub(a, b)}")
add.py
содержит:
def add(a, b):
return a+b
И sub.py
содержит:
def sub(a, b):
return ab
Прямо за пределами calc
можно выполнить сценарий, а логика внутри
__main__.py
будет выполняться путем вызова:
python3 calc
{.ezlazyload}
Эта структура также дает более четкое представление о расположении
рабочей области, о том, как организованы каталоги, а точка входа
определяется внутри отдельного файла с именем __main__.py
.
Заключение
__name__ == "__main__"
запускает блоки кода только тогда, когда наш
скрипт Python выполняется непосредственно от пользователя. Это мощно,
так как позволяет нашему коду вести себя по-разному, когда он
выполняется как программа, а не импортируется как модуль.
При написании больших модулей мы можем выбрать более структурированный
подход с использованием __main__.py
для запуска модуля. Для
автономного скрипта, включая if __name__ == "__main__"
, более простой
метод отделения API от программы.