6

Почему использовать def main()?

10

Вопрос по Python: Зачем использовать конструкцию if __name__ == "__main__":?

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

def main():
    # мой код здесь

if __name__ == "__main__":
    main()

Но в чем же дело? Есть ли какие-то причины не определять функции вверху файла и просто писать код под ними? Например:

def my_function():
    # мой код здесь

def my_function_two():
    # мой код здесь

# какой-то код
# вызов функции
# print(что-то)

Мне просто интересно, есть ли какой-то смысл в использовании main? Почему это считается хорошей практикой?

4 ответ(ов)

6

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

if __name__ == "__main__":
    # Код, который должен выполняться только при запуске файла как основного скрипта

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

2

Хотя другие уже ответили на этот вопрос, я думаю, у меня есть что добавить.

Вот несколько причин, почему стоит использовать условие if, вызывающее main() (в произвольном порядке):

  • В других языках (например, C и Java) есть функция main(), которая вызывается при выполнении программы. Используя этот if, мы можем сделать так, чтобы Python вёл себя аналогично, что будет более привычно для многих людей.
  • Код станет чище, легче читаемым и лучше организованным. (Да, я понимаю, что это субъективно).
  • Это позволит import этот код Python как модуль без неприятных побочных эффектов.
  • Это даст возможность запускать тесты на этом коде.
  • Это позволит импортировать код в интерактивную оболочку Python и тестировать/отлаживать/запускать его.
  • Переменные внутри def main являются локальными, в то время как те, что снаружи — глобальными. Это может привести к неожиданным ошибкам и поведению.

Однако вы не обязаны писать функцию main() и вызывать её внутри условия if.

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

Даже если вы поместите код внутри функции main, никто не требует делать это именно так. Есть аккуратный вариант:

import sys

def main(argv):
    # Мой код здесь
    pass

if __name__ == "__main__":
    main(sys.argv)

Это позволяет вызывать main() из других скриптов (или из интерактивной оболочки), передавая настраиваемые параметры. Это может быть полезно в юнит-тестах или при пакетной обработке. Но помните, что приведённый выше код требует парсинга argv, так что, возможно, лучше использовать другой вызов, который будет передавать уже разобранные параметры.

В объектно-ориентированном приложении, которое я написал, код выглядел так:

class MyApplication(something):
    # Мой код здесь

if __name__ == "__main__":
    app = MyApplication()
    app.run()

Так что не стесняйтесь писать код так, как вам удобнее. 😃

0

Файл foo.py можно использовать двумя способами.

  1. Импорт в другой файл: import foo

    В этом случае значение __name__ будет равно foo, и код в условии if __name__ == '__main__': не выполнится, поэтому XXXX не будет напечатано.

  2. Прямое выполнение: python foo.py

    Когда файл выполняется напрямую, значение __name__ становится равным __main__, и код в секции if выполняется, в результате чего будет напечатано XXXX.

Одно из применений этой функциональности — написание различных модульных тестов внутри одного и того же модуля.

0

Если вы рассматриваете второй скрипт, то при его импорте в другой скрипт инструкции, находящиеся на "глобальном уровне", будут выполнены. Это поведение связано с тем, что при импорте модуля Python исполняет весь код на верхнем уровне этого модуля, что может привести к нежелательным эффектам, если вы не учитываете этот момент. Поэтому рекомендуется помещать код, который не должен выполняться при импорте, внутрь конструкции if __name__ == "__main__":. Это позволит вам контролировать, что именно будет исполняться при прямом запуске скрипта или его импорте.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь