Что делать, если __name__ == "__main__": делать? - PullRequest
5063 голосов
/ 07 января 2009

Что делает if __name__ == "__main__":?

# Threading example
import time, thread

def myfunction(string, sleeptime, lock, *args):
    while True:
        lock.acquire()
        time.sleep(sleeptime)
        lock.release()
        time.sleep(sleeptime)

if __name__ == "__main__":
    lock = thread.allocate_lock()
    thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
    thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

Ответы [ 28 ]

32 голосов
/ 11 декабря 2013

Когда вы запускаете Python в интерактивном режиме, локальной переменной __name__ присваивается значение __main__. Аналогично, когда вы выполняете модуль Python из командной строки, а не импортируете его в другой модуль, его атрибуту __name__ присваивается значение __main__, а не фактическое имя модуля. Таким образом, модули могут смотреть на свое собственное значение __name__, чтобы определить для себя, как они используются, в качестве поддержки другой программы или в качестве основного приложения, выполняемого из командной строки. Таким образом, следующая идиома довольно распространена в модулях Python:

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.
29 голосов
/ 22 августа 2017

Рассмотрим:

if __name__ == "__main__":
    main()

Проверяет, является ли атрибут __name__ скрипта Python "__main__". Другими словами, если сама программа выполняется, атрибут будет __main__, поэтому программа будет выполнена (в этом случае функция main()).

Однако, если ваш скрипт на Python используется модулем, будет выполнен любой код вне оператора if, поэтому if \__name__ == "\__main__" используется просто для проверки, используется ли программа в качестве модуля или нет, и, следовательно, решает, нужно ли запускать код.

25 голосов
/ 03 апреля 2018

Прежде чем что-либо объяснять о if __name__ == '__main__', важно понять, что такое __name__ и что оно делает.

Что такое __name__?

__name__ - это DunderAlias ​​ - может рассматриваться как глобальная переменная (доступная из модулей) и работает аналогично global.

Это строка (глобальная, как упоминалось выше), обозначенная type(__name__) (получая <class 'str'>), и является встроенным стандартом для Python 3 и Python 2 версии.

Где:

Его можно использовать не только в скриптах, но и в интерпретаторе, и в модулях / пакетах.

Переводчик:

>>> print(__name__)
__main__
>>>

Сценарий:

test_file.py

print(__name__)

В результате __main__

Модуль или упаковка:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

В результате somefile

Обратите внимание, что при использовании в пакете или модуле __name__ принимает имя файла. Путь к действительному модулю или пути пакета не указан, но имеет свой собственный DunderAlias ​​__file__, который учитывает это.

Вы должны увидеть, что, где __name__, где находится основной файл (или программа), будет всегда возвращать __main__, и если это модуль / пакет, или что-либо, что работает от какого-либо другого скрипта Python, вернет имя файла, из которого он произошел.

Практика:

Если переменная означает, что ее значение может быть перезаписано («может» не означает «следует»), перезапись значения __name__ приведет к недостаточной читаемости. Так что не делай этого ни по какой причине. Если вам нужна переменная, определите новую переменную.

Всегда предполагается, что значением __name__ будет __main__ или именем файла. Повторное изменение этого значения по умолчанию вызовет еще большую путаницу в том, что оно пойдет на пользу, и вызовет проблемы в дальнейшем.

пример:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

В целом считается хорошей практикой включать if __name__ == '__main__' в сценарии.

Теперь, чтобы ответить if __name__ == '__main__':

Теперь мы знаем, как поведение __name__ становится понятнее:

if - это оператор управления потоком, который содержит блок кода, который будет выполняться, если заданное значение равно true. Мы видели, что __name__ может принимать либо __main__ или имя файла, из которого оно было импортировано.

Это означает, что если __name__ равно __main__, то этот файл должен быть основным файлом и фактически должен быть запущен (или интерпретатором), а не модулем или пакетом, импортированным в сценарий.

Если действительно __name__ принимает значение __main__, то все, что находится в этом блоке кода, будет выполняться.

Это говорит нам о том, что если выполняемый файл является основным файлом (или вы запускаете непосредственно из интерпретатора), то это условие должно выполняться. Если это пакет, то не должен, и значение не будет __main__.

Модули:

__name__ также может использоваться в модулях для определения имени модуля

Варианты:

Можно также делать другие, менее распространенные, но полезные вещи с __name__, некоторые я покажу здесь:

Выполняется, только если файл является модулем или пакетом:

if __name__ != '__main__':
    # Do some useful things 

Запуск одного условия, если файл является основным, и другого, если это не так:

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

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

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

21 голосов
/ 30 ноября 2016

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

__name__: Каждый модуль в Python имеет специальный атрибут, который называется __name__. Это встроенная переменная, которая возвращает имя модуля.

__main__: Как и другие языки программирования, Python также имеет точку входа для выполнения, то есть main. '__main__' - это имя области, в которой выполняется код верхнего уровня . По сути, у вас есть два способа использования модуля Python: запустить его непосредственно как скрипт или импортировать его. Когда модуль запускается как скрипт, его __name__ устанавливается на __main__.

Таким образом, значение атрибута __name__ устанавливается на __main__, когда модуль запускается в качестве основной программы. В противном случае значение __name__ должно содержать имя модуля.

20 голосов
/ 24 января 2013

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

Это может быть написано несколькими способами. Другое это:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

Я не говорю, что вы должны использовать это в рабочем коде, но это служит иллюстрацией того, что в if __name__ == '__main__' нет ничего «волшебного». Это хорошее соглашение для вызова основной функции в файлах Python.

19 голосов
/ 25 ноября 2015

Существует ряд переменных, которые система (интерпретатор Python) предоставляет для исходных файлов (модулей). Вы можете получить их значения в любое время, поэтому давайте сосредоточимся на __ name __ variable / attribute:

Когда Python загружает файл исходного кода, он выполняет весь найденный в нем код. (Обратите внимание, что он не вызывает все методы и функции, определенные в файле, но определяет их.)

Перед тем, как интерпретатор выполнит файл исходного кода, он определит несколько специальных переменных для этого файла; __name __ - одна из тех специальных переменных, которые Python автоматически определяет для каждого файла исходного кода.

Если Python загружает этот файл исходного кода в качестве основной программы (то есть файла, который вы запускаете), то он устанавливает специальную переменную __ name __ для этого файла, чтобы иметь значение "__ main __" .

Если это импортируется из другого модуля, __name __ будет установлено на имя этого модуля.

Итак, в вашем примере частично:

if __name__ == "__main__":
   lock = thread.allocate_lock()
   thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
   thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

означает, что код блока:

lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

будет выполняться только при непосредственном запуске модуля; блок кода не будет выполняться, если другой модуль вызывает / импортирует его, потому что значение __name __ не будет равно " main " в данном конкретном случае.

Надеюсь, это поможет.

16 голосов
/ 24 апреля 2016

if __name__ == "__main__": - это, по сути, среда сценариев верхнего уровня, в которой указывается интерпретатор, который («У меня самый высокий приоритет для выполнения первым»).

'__main__' - это имя области, в которой выполняется код верхнего уровня. __name__ модуля устанавливается равным '__main__' при чтении из стандартного ввода, сценария или из интерактивного приглашения.

if __name__ == "__main__":
    # Execute only if run as a script
    main()
14 голосов
/ 22 сентября 2017

причина

if __name__ == "__main__":
    main()

в первую очередь позволяет избежать проблем import import , которые могут возникнуть из-за , когда код импортирован напрямую . Вы хотите, чтобы main() запускался, если ваш файл был вызван напрямую (это случай __name__ == "__main__"), но если ваш код был импортирован, то импортер должен ввести ваш код из истинного основного модуля, чтобы избежать проблем блокировки импорта.

Побочным эффектом является то, что вы автоматически входите в методологию, которая поддерживает несколько точек входа. Вы можете запустить вашу программу, используя main() в качестве точки входа, , но вам не нужно . В то время как setup.py ожидает main(), другие инструменты используют альтернативные точки входа. Например, чтобы запустить ваш файл как процесс gunicorn, вы определяете функцию app() вместо main(). Как и в случае setup.py, gunicorn импортирует ваш код, поэтому вы не хотите, чтобы он что-либо делал во время импорта (из-за проблемы с блокировкой импорта).

13 голосов
/ 24 июня 2018

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

Чтобы быть коротким, нужно знать несколько моментов:

  1. import a действие фактически запускает все, что может быть выполнено в «а»

  2. Из-за пункта 1 вы, возможно, не захотите, чтобы все выполнялось в «a» при его импорте

  3. Чтобы решить проблему в пункте 2, python позволяет поставить проверку состояния

  4. __name__ - неявная переменная во всех модулях .py; когда импортируется a.py, значение __name__ модуля a.py устанавливается равным его имени файла «a»; когда a.py запускается напрямую с использованием «python a.py», что означает, что a.py является точкой входа, тогда значение __name__ модуля a.py устанавливается в строку __main__

  5. Основываясь на механизме, которым python устанавливает переменную __name__ для каждого модуля, знаете ли вы, как достичь пункта 3? Ответ довольно прост, верно? Поставить условие if: if __name__ == "__main__": ...; Вы можете даже поставить, если __name__ == "a" в зависимости от ваших функциональных потребностей

Важной особенностью Python является точка 4! Остальное - просто базовая логика.

13 голосов
/ 22 июня 2016

Рассмотрим:

print __name__

Выход для вышеупомянутого - __main__.

if __name__ == "__main__":
  print "direct method"

Вышеприведенное утверждение верно и печатает «прямой метод» . Предположим, что если они импортировали этот класс в другой класс, он не печатает «прямой метод» , поскольку при импорте он установит __name__ equal to "first model name".

...