Что делать, если __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 ]

5419 голосов
/ 07 января 2009

Всякий раз, когда интерпретатор Python читает исходный файл, он делает две вещи:

  • устанавливает несколько специальных переменных, таких как __name__, а затем

  • выполняет весь код, найденный в файле.

Давайте посмотрим, как это работает и как это связано с вашим вопросом о __name__ проверках, которые мы всегда видим в скриптах Python.

Пример кода

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

# Suppose this is foo.py.

print("before import")
import math

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

print("before functionB")
def functionB():
    print("Function B {}".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    functionA()
    functionB()
print("after __name__ guard")

Специальные переменные

Когда интерпретатор Python читает исходный файл, он сначала определяет несколько специальных переменных. В этом случае мы заботимся о переменной __name__.

Когда ваш модуль является основной программой

Если вы используете свой модуль (исходный файл) в качестве основной программы, например,

python foo.py

интерпретатор назначит жестко закодированную строку "__main__" переменной __name__, т.е.

# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

Когда ваш модуль импортируется другим

С другой стороны, предположим, что какой-то другой модуль является основной программой и импортирует ваш модуль. Это означает, что в основной программе или в каком-либо другом модуле основная программа импортирует такой оператор:

# Suppose this is in some other main program.
import foo

В этом случае интерпретатор посмотрит имя файла вашего модуля, foo.py, уберет .py и назначит эту строку для переменной __name__ вашего модуля, то есть

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

Выполнение кода модуля

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

Всегда

  1. Печатает строку "before import" (без кавычек).

  2. Загружает модуль math и присваивает его переменной с именем math. Это эквивалентно замене import math следующим (обратите внимание, что __import__ - это низкоуровневая функция в Python, которая принимает строку и запускает фактический импорт):

# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. Печатает строку "before functionA".

  2. Выполняет блок def, создает объект функции, затем присваивает этот объект функции переменной с именем functionA.

  3. Печатает строку "before functionB".

  4. Выполняет второй блок def, создает другой функциональный объект, затем присваивает его переменной с именем functionB.

  5. Он печатает строку "before __name__ guard".

Только когда ваш модуль является основной программой

  1. Если ваш модуль является основной программой, то он увидит, что __name__ действительно установлен на "__main__", и вызовет две функции, печатая строки "Function A" и "Function B 10.0".

Только когда ваш модуль импортируется другим

  1. ( вместо ) Если ваш модуль не является основной программой, но был импортирован другой, то __name__ будет "foo", а не "__main__", и пропустит тело if заявление.

Всегда

  1. В обоих случаях будет напечатана строка "after __name__ guard".

Резюме

Итак, вот что будет напечатано в двух случаях:

# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard

Почему это так работает?

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

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

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

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

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

Пища для размышлений

  • Вопрос: Могу ли я иметь несколько __name__ проверочных блоков? Ответ: это странно, но язык не остановит вас.

  • Предположим, что в foo2.py указано следующее. Что произойдет, если вы скажете python foo2.py в командной строке? Почему?

# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")
  • Теперь выясните, что произойдет, если вы уберете __name__ проверку foo3.py:
# Suppose this is foo3.py.

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")
  • Что это будет делать при использовании в качестве сценария? Когда импортируется как модуль?
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")
1635 голосов
/ 07 января 2009

Когда ваш скрипт запускается путем передачи его в качестве команды интерпретатору Python,

python myscript.py

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

В этом случае код верхнего уровня - это блок if. __name__ - это встроенная переменная, которая оценивает имя текущего модуля. Однако, если модуль запускается напрямую (как в myscript.py выше), тогда вместо __name__ устанавливается строка "__main__". Таким образом, вы можете проверить, выполняется ли ваш скрипт напрямую или импортируется чем-то другим, проверяя

if __name__ == "__main__":
    ...

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

# file one.py
def func():
    print("func() in one.py")

print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")
# file two.py
import one

print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")

Теперь, если вы вызываете переводчика как

python one.py

Выход будет

top-level in one.py
one.py is being run directly

Если вы запустите two.py вместо:

python two.py

Вы получаете

top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly

Таким образом, когда загружается модуль one, его __name__ равен "one" вместо "__main__".

651 голосов
/ 07 января 2009

Самое простое объяснение переменной __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__'] в этом модуле на имя модуля. Также при импорте запускается весь код в модуле. Поскольку оператор if оценивается как False, эта часть не выполняется.

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

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

467 голосов
/ 23 ноября 2013

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

Чтобы обрисовать основы:

  • Глобальная переменная __name__ в модуле, являющемся точкой входа в вашу программу, равна '__main__'. В противном случае это имя, по которому вы импортируете модуль.

  • Итак, код в блоке if будет работать только в том случае, если модуль является точкой входа в вашу программу.

  • Позволяет импортировать код из модуля другими модулями, не выполняя блок кода ниже при импорте.


Зачем нам это нужно?

Разработка и тестирование вашего кода

Допустим, вы пишете скрипт Python, предназначенный для использования в качестве модуля:

def do_important():
    """This function does something very important"""

Вы можете протестировать модуль, добавив этот вызов функции внизу:

do_important()

и запустить его (из командной строки) с чем-то вроде:

~$ python important.py

Проблема

Однако, если вы хотите импортировать модуль в другой скрипт:

import important

При импорте вызывается функция do_important, так что вы, вероятно, закомментируете свой вызов функции, do_important(), внизу.

# do_important() # I must remember to uncomment to execute this!

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

Лучший путь

Переменная __name__ указывает на пространство имен, где бы ни находился интерпретатор Python в данный момент.

Внутри импортированного модуля это имя этого модуля.

Но внутри основного модуля (или интерактивного сеанса Python, т.е. чтения, Eval, Print Loop или REPL интерпретатора) вы запускаете все, начиная с "__main__".

Итак, если вы проверите перед выполнением:

if __name__ == "__main__":
    do_important()

С учетом вышеизложенного ваш код будет выполняться только тогда, когда вы запускаете его в качестве основного модуля (или намеренно вызываете его из другого скрипта).

Еще лучше

Тем не менее, есть Pythonic способ улучшить это.

Что если мы хотим запустить этот бизнес-процесс извне модуля?

Если мы добавим код, который мы хотим использовать при разработке и тестировании в подобной функции, а затем проведем проверку на '__main__' сразу после:

def main():
    """business logic for when running this module as the primary one!"""
    setup()
    foo = do_important()
    bar = do_even_more_important(foo)
    for baz in bar:
        do_super_important(baz)
    teardown()

# Here's our payoff idiom!
if __name__ == '__main__':
    main()

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

Это позволит импортировать модуль и его функции и классы в другие скрипты без запуска функции main, а также позволит вызывать модуль (и его функции и классы) при запуске из другого '__main__' модуль, т.е.

import important
important.main()

Эту идиому также можно найти в документации по Python в объяснении модуля __main__. Этот текст гласит:

Этот модуль представляет (иначе анонимную) область, в которой выполняется основная программа интерпретатора - команды читаются либо из стандартный ввод, из файла скрипта или из интерактивного приглашения. Это это среда, в которой идиоматический «условный сценарий» строфа запускает скрипт:

if __name__ == '__main__':
    main()
107 голосов
/ 07 января 2009

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

70 голосов
/ 15 октября 2014

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

__name__ - это глобальная переменная (в Python глобальная означает на уровне модуля ), которая существует во всех пространствах имен. Обычно это имя модуля (типа str).

Как единственный особый случай, однако, в любом процессе Python, который вы запускаете, как в mycode.py:

python mycode.py

в противном случае анонимному глобальному пространству имен присваивается значение '__main__' его __name__.

Таким образом, включая последние строки

if __name__ == '__main__':
    main()
  • в конце вашего скрипта mycode.py,
  • когда это основной модуль точки входа, запускаемый процессом Python,

приведет к запуску уникально определенной функции main вашего скрипта.

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

import mycode
# ... any amount of other code
mycode.main()
61 голосов
/ 29 сентября 2016

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

Взять файл "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(); ок, печать ' периферийное задание: может быть полезно в других проектах '.
  • Что это? if заявление. Итак, условие выполнено (переменная __name__ была установлена ​​на "__main__"), поэтому я войду в функцию main() и выведу основную функцию : здесь действие .

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

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

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

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

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

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

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

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

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

45 голосов
/ 03 апреля 2013

Когда в нашем модуле есть определенные операторы (M.py), которые мы хотим выполнить, когда он будет работать как основной (не импортированный), мы можем поместить эти операторы (тестовые случаи, операторы печати) в этот if блок.

Как и по умолчанию (когда модуль работает как основной, а не импортированный), переменная __name__ устанавливается на "__main__", а когда она будет импортирована, переменная __name__ получит другое значение, наиболее вероятно имя модуля ('M'). Это полезно для совместного запуска различных вариантов модулей и разделения их конкретных операторов ввода и вывода, а также при наличии тестов.

Вкратце , используйте этот блок 'if __name__ == "main"', чтобы предотвратить запуск (определенного) кода при импорте модуля.

35 голосов
/ 20 января 2015

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

Предположим, у нас есть этот код в x.py:

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

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

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

35 голосов
/ 15 октября 2016

Проще говоря, __name__ - это переменная, определенная для каждого сценария, которая определяет, выполняется ли сценарий как основной модуль или как импортированный модуль.

Так что, если у нас есть два сценария;

#script1.py
print "Script 1's name: {}".format(__name__)

и

#script2.py
import script1
print "Script 2's name: {}".format(__name__)

Результат выполнения script1 равен

Script 1's name: __main__

И результат выполнения script2:

Script1's name is script1
Script 2's name: __main__

Как видите, __name__ сообщает нам, какой код является «основным» модулем. Это замечательно, потому что вы можете просто написать код и не беспокоиться о структурных проблемах, как в C / C ++, где, если файл не реализует функцию main, он не может быть скомпилирован как исполняемый файл, и если он это делает, затем его нельзя использовать в качестве библиотеки.

Допустим, вы пишете скрипт на Python, который делает что-то великолепное, и вы реализуете множество функций, которые полезны для других целей. Если я хочу использовать их, я могу просто импортировать ваш скрипт и использовать их без выполнения вашей программы (учитывая, что ваш код выполняется только в контексте if __name__ == "__main__":). В то время как в C / C ++ вам придется разделить эти части на отдельный модуль, который затем включает файл. Изобразите ситуацию ниже;

Complicated importing in C

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

Elegant importing in Python

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

...