python это '__main__' - Что делать, если __name__ == "__main__": делать?




14 Answers

Когда интерпретатор Python читает исходный файл, он выполняет весь найденный в нем код.

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

В случае вашего скрипта предположим, что он выполняет главную функцию, например, вы сказали что-то вроде

python threading_example.py

в командной строке. После настройки специальных переменных он выполнит оператор import и загрузит эти модули. Затем он будет оценивать блок def , создавая объект функции и создавая переменную myfunction которая указывает на объект функции. Затем он прочитает инструкцию if и увидит, что __name__ равно "__main__" , поэтому он выполнит показанный там блок.

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

Дополнительную информацию см. На этой странице .

Примечание (по Stainsor): Если вы поместите код перед определениями функций, он будет выполняться перед main.

print("This code executes before main.") 

def functionA():
    print("Function A")

def functionB():
    print("Function B")

if __name__ == '__main__':
    functionA()
    functionB()

Если этот модуль действительно является основным, этот код приводит к:

This code executes before main. 
Function A 
Function B

Если этот модуль не является основным, вы получаете:

This code executes before main. 
функция атрибут

Что делает 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))



Простейшим объяснением переменной __name__ (imho) является следующее:

Создайте следующие файлы.

# a.py
import b

а также

# b.py
print "Hello World from %s!" % __name__

if __name__ == '__main__':
    print "Hello World again from %s!" % __name__

Запуск их даст вам этот результат:

$ python a.py
Hello World from b!

Как вы можете видеть, когда модуль импортируется, Python устанавливает globals()['__name__'] в этом модуле к имени модуля.

$ python b.py
Hello World from __main__!
Hello World again from __main__!

Как вы можете видеть, когда файл выполняется, Python устанавливает globals()['__name__'] в этом файле на "__main__" .




if __name__ == "__main__" - это часть, которая запускается, когда сценарий запускается из (скажем) командной строки с помощью команды python myscript.py .




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

Возьмите файл «ab.py»:

def a():
    print('A function in ab file');
a()

И второй файл «xy.py»:

import ab
def main():
    print('main function: this is where the action is')
def x():
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

Что делает этот код на самом деле?

Когда вы выполняете xy.py , вы import ab . Оператор import запускает модуль сразу при импорте, поэтому операции ab выполняются до остальной части xy . Закончив с ab , он продолжит с xy .

Интерпретатор отслеживает, какие сценарии работают с __name__ . Когда вы запускаете скрипт - независимо от того, что вы его назвали, интерпретатор называет его "__main__" , что делает его мастером или «домашним» скриптом, который возвращается после запуска внешнего скрипта.

Любой другой скрипт, который вызывается из этого сценария "__main__" присваивается его имени файла как его __name__ (например, __name__ == "ab.py" ). Следовательно, строка, if __name__ == "__main__": это тест интерпретатора, чтобы определить, является ли это интерпретация / анализ исходного сценария дома, который был первоначально выполнен, или если он временно заглянет в другой (внешний) скрипт. Это дает гибкость программисту, чтобы сценарий вел себя по-другому, если он выполняется напрямую или вызван извне.

Давайте рассмотрим вышеприведенный код, чтобы понять, что происходит, сосредоточившись сначала на незаметных строках и порядке, которые они отображают в сценариях. Помните, что функции - или def - блоки не делают ничего сами по себе, пока не будут вызваны. Что может сказать интерпретатор, если пробормотал себе:

  • Откройте файл xy.py как «домашний» файл; назовите его "__main__" в переменной __name__ .
  • Импортируйте и откройте файл с __name__ == "ab.py" .
  • О, функция. Я это запомню.
  • Хорошо, функция a() ; Я только что узнал об этом. Печать « Функция в ab-файле ».
  • Конец файла; вернуться к "__main__" !
  • О, функция. Я это запомню.
  • Другой.
  • Функция x() ; ok, печать « периферийная задача: может быть полезна в других проектах ».
  • Что это? Оператор if . Ну, условие выполнено (переменная __name__ установлена ​​на "__main__" ), поэтому я буду вводить функцию main() и печатать « главную функцию: это то, где действие ».

Нижние две строки означают: «Если это сценарий "__main__" или« home », выполните функцию main() ». Вот почему вы увидите def main(): block up top, который содержит основной поток функций скрипта.

Зачем это реализовать?

Помните, что я сказал ранее о заявках на импорт? При импорте модуля он не просто «распознает» его и ждет дальнейших инструкций - он фактически выполняет все исполняемые операции, содержащиеся в скрипте. Таким образом, добавление мяса вашего скрипта в функцию main() эффективно помещает его в карантин, изолируя его, чтобы он не сразу запускался при импорте с помощью другого скрипта.

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

Но код работает без него

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

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

Разделяя независимые функции, вы получаете возможность повторно использовать свою предыдущую работу, вызвав их в другой скрипт. Например, «example.py» может импортировать «xy.py» и вызвать x() , используя функцию «x» из «xy.py». (Может быть, это заглавное третье слово данной текстовой строки, создание массива NumPy из списка чисел и возведение в квадрат их или деление 3D-поверхности. Возможности безграничны).

(В стороне этот вопрос содержит ответ от @kindall, который, наконец, помог мне понять - почему, а не как. К сожалению, он был отмечен как дубликат этого , который, я думаю, является ошибкой.)




Давайте рассмотрим ответ более абстрактным образом:

Предположим, что мы имеем этот код в x.py:

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

Блоки A и B запускаются, когда мы запускаем «x.py».

Но только блок A (а не B) запускается, когда мы запускаем другой модуль, например «y.py», в котором xy импортируется и код запускается оттуда (например, когда функция в «x.py» вызывается из y.py).




При интерактивном запуске 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.



Прежде чем объяснять что-либо о 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, вернет имя файла откуда оно возникло.

Практика:

Быть переменной означает, что ее значение может быть перезаписано («can» не означает «should»), перезаписывая значение __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 это оператор управления потоком, содержащий блок кода, будет выполняться, если заданное значение истинно. Мы видели, что __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

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

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




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

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

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

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




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

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

if __name__ == "__main__":
    # Execute only if run as a script
    main()



Вы можете сделать файл полезным как скрипт, так и импортируемый модуль .

fibo.py (модуль с именем fibo )

# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

Ссылка: https://docs.python.org/3.5/tutorial/modules.html




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

Короче говоря, вам нужно знать несколько моментов:

  1. import a действия фактически запускает все, что можно запустить в "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. На основе механизма, как питон устанавливает переменную __name__для каждого модуля, знаете ли вы, как достичь точки 3? Ответ довольно прост, не так ли? Помещенный если условие: if __name__ == "__main__": ...; вы можете даже поставить, если в __name__ == "a"зависимости от вашей функциональной потребности

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




Создайте файл, a.py :

print(__name__) # It will print out __main__

__name__всегда равно __main__всякий раз, когда этот файл запускается напрямую, показывая, что это основной файл.

Создайте другой файл, b.py , в том же каталоге:

import a  # Prints a

Запустить его. Он напечатает , то есть имя файла , который импортируется .

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

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly



Этот ответ предназначен для Java-программистов, изучающих Python. Каждый файл Java обычно содержит один открытый класс. Вы можете использовать этот класс двумя способами:

  1. Вызовите класс из других файлов. Вам просто нужно импортировать его в вызывающую программу.

  2. Запустите класс отдельно для тестирования.

В последнем случае класс должен содержать общедоступный метод static void main (). В Python этой цели служит глобально определенная метка '__main__'.




Недавно я столкнулся с этим, создав класс в python (глубокое обучение) и, насколько мне известно, и в соответствии с вышеприведенными пояснениями выше, я разработаю

__name__=="__main__"

Поскольку иногда мы строим класс в .py-файле и определяем много функций внутри этого класса. но мы не хотим обрабатывать все эти функции класса для одной цели. например, для создания класса и определения некоторых функций для создания данных (файлы .npy), а некоторые для загрузки данных. поэтому, если мы определим

__name__=="__main__"

ххх = имя_класса ()

xxx.create_data ()

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




Related