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




13 Answers

Когда ваш скрипт запускается, передавая его как команду интерпретатору 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

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

функция 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))



Что делает 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() внизу.

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

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

Лучший способ

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

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

Но внутри первичного модуля (или интерактивного сеанса Python, т. Е. Read, 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()



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



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

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

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




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

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

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

а также

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

Результатом выполнения скрипта 1 является

Script 1's name: __main__

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

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

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

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

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

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




Рассматривать:

if __name__ == "__main__":
    main()

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

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




Существует ряд переменных, которые система (интерпретатор 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 » в этом конкретном экземпляре.

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




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

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

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

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




Причина для

if __name__ == "__main__":
    main()

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

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




Рассматривать:

print __name__

Вывод для выше - __main__ .

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

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




Если этот .py-файл импортируется другими .py-файлами, код под «оператором if» не будет выполнен.

Если этот .py запускается python this_py.pyпод оболочкой или дважды щелкнут в Windows. будет выполнен код под «оператором if».

Обычно он предназначен для тестирования.




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

Предположим, что у вас есть два файла Python, a.py и b.py. Теперь, a.py импортирует b.py. Мы запускаем файл a.py, где сначала выполняется код «import b.py». Перед тем как остальная часть кода a.py запускается, код в файле b.py должен выполняться полностью.

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

Так вот эта строка проверки кода. Если это основной файл (т. Е. B.py), запускающий код, который в этом случае не является (a.py является основным файлом), тогда выполняется только код.




если имя == ' main ':

Мы видим, что __name__ == '__main__':довольно часто.

Он проверяет, импортирован ли модуль или нет.

Другими словами, код внутри ifблока будет выполняться только при прямом запуске кода. Здесь directlyозначает not imported.

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

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

Если мы запускаем код напрямую python test.py, имя модуля __main__:

call test()
test module name=__main__



Related