[python] __name__ ==“__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__다음

  • 파일에서 찾은 모든 코드를 실행합니다.

이것이 어떻게 작동하고 __name__파이썬 스크립트에서 항상 볼 수 있는 검사 에 대한 질문과 어떻게 관련되는지 봅시다 .

코드 샘플

약간 다른 코드 샘플을 사용하여 가져 오기 및 스크립트 작동 방식을 살펴 보겠습니다. 다음 파일이 파일에 있다고 가정하십시오 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 interpeter는 소스 파일을 읽을 때 먼저 몇 가지 특수 변수를 정의합니다. 이 경우 __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파일을 검색하고 (몇 가지 다른 변형 검색과 함께) 해당 모듈을 실행하기 전에 "foo"import 문에서 __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__파이썬에서 문자열을 가져 와서 실제 가져 오기를 트리거하는 저수준 함수입니다).

# 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", not "__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")


답변

스크립트를 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__".


답변

__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!

보시다시피, 모듈을 가져올 때 파이썬은 globals()['__name__']이 모듈에서 모듈 이름으로 설정합니다. 또한 가져 오면 모듈의 모든 코드가 실행됩니다. 이 부분으로 if평가 된 문장 False은 실행되지 않습니다.

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

보다시피, 파일이 실행될 때 파이썬은 globals()['__name__']이 파일에서로 설정 합니다 "__main__". 이번에는 if명령문이 평가되어 True실행 중입니다.


답변

무엇을 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 세션, 즉 인터프리터의 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()

이 관용구는 또한 파이썬 문서에서 __main__모듈 에 대한 설명에서 찾을 수 있습니다 . 그 내용은 다음과 같습니다.

이 모듈은 인터프리터의 기본 프로그램이 실행하는 (그렇지 않은 익명의) 범위를 나타냅니다. 명령은 표준 입력, 스크립트 파일 또는 대화식 프롬프트에서 읽습니다. 관용적 인 “조건부 스크립트”스탠자가 스크립트를 실행하는 환경은 다음과 같습니다.

if __name__ == '__main__':
    main()

답변

if __name__ == "__main__"는 같은 명령을 사용하여 명령 줄에서 스크립트를 실행할 때 실행되는 부분입니다 python myscript.py.


답변

무엇을 if __name__ == "__main__":합니까?

__name__는 모든 네임 스페이스에 존재 하는 전역 변수 (Python에서 전역은 실제로 모듈 레벨을 의미 함 )입니다. 일반적으로 모듈 이름 ( str유형)입니다.

그러나 유일한 특별한 경우로, mycode.py에서와 같이 실행하는 모든 Python 프로세스에서 :

python mycode.py

그렇지 않으면 익명 글로벌 네임 스페이스의 값이 할당됩니다 '__main__'의로를 __name__.

따라서 마지막 줄을 포함 하여

if __name__ == '__main__':
    main()
  • mycode.py 스크립트 끝에서
  • 파이썬 프로세스에 의해 실행되는 기본 엔트리 포인트 모듈 인 경우

스크립트의 고유하게 정의 된 main함수가 실행됩니다.

이 구문을 사용하면 얻을 수있는 또 다른 이점 : 코드를 다른 스크립트에서 모듈로 가져 와서 프로그램이 결정할 때 주 함수를 실행할 수도 있습니다.

import mycode
# ... any amount of other code
mycode.main()


답변

문제의 코드 메커니즘 인 “어떻게”에 대한 다양한 설명이 여기에 있지만 “왜”를 이해하기 전까지는 아무런 의미가 없습니다. 이것은 새로운 프로그래머에게 특히 유용합니다.

“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를 ‘home’파일로여십시오. 변수 "__main__"에서 호출하십시오 __name__.
  • 로 파일을 가져오고 엽니 다 __name__ == "ab.py".
  • 아, 기능. 나는 그것을 기억할 것이다.
  • 좋아, 기능 a(); 방금 배웠습니다. ‘ ab 파일의 기능 ‘인쇄 중 .
  • 파일의 끝; 다시 "__main__"!
  • 아, 기능. 나는 그것을 기억할 것이다.
  • 다른 것.
  • 기능 x(); 좋아, ‘ 주변 작업 : 다른 프로젝트에서 유용 할 수 있습니다 ‘인쇄 .
  • 이게 뭐야? if문. 조건이 충족되었으므로 (변수 __name__가으로 설정 됨 "__main__") main()함수에 들어가서 ‘ 주요 기능 :이 위치는 작업 위치 ‘를 인쇄 하겠습니다 .

맨 아래 두 줄은 “이것이” "__main__"또는 “홈”스크립트 인 경우 main()” 라는 함수를 실행하십시오 . 그렇기 때문에 def main():스크립트 기능의 주요 흐름이 포함 된 블록 업 이 표시 됩니다.

왜 이것을 구현해야합니까?

수입 명세서에 대해 앞서 말한 것을 기억하십니까? 모듈을 가져 오면 모듈을 ‘인식’하고 추가 지시를 기다리는 것이 아니라 실제로 스크립트 내에 포함 된 모든 실행 가능한 작업을 실행합니다. 따라서 스크립트의 고기를 main()함수에 넣으면 효과적으로 격리되어 다른 스크립트로 가져올 때 즉시 실행되지 않도록 격리됩니다.

다시 한 번 예외가 있지만 일반적 main()으로 일반적으로 외부에서 호출되지 않는 것이 일반적입니다. 그래서 당신은 한 가지 더 궁금 할 것입니다 : 우리가 전화하지 않으면 main()왜 우리는 스크립트를 부르는 것입니까? 많은 사람들이 파일의 나머지 코드와 독립적으로 실행되도록 작성된 독립형 함수로 스크립트를 구성하기 때문입니다. 그런 다음 나중에 스크립트 본문의 다른 곳에서 호출됩니다. 어느 것이 나를 이끌어 줍니까?

그러나 코드는 그것없이 작동합니다

네 맞습니다. 이러한 개별 함수 함수 내에 포함되지 않은 인라인 스크립트에서 호출 할 수 있습니다 main(). 당신이 (필자의 초기 학습 단계에서) 당신이 필요로하는 것을 정확하게 수행하는 인라인 스크립트를 만드는 데 익숙하다면, 당신은 그 작업이 다시 필요할 때 다시 알아 내려고 노력할 것입니다. 글쎄, 당신은 코드에 대한 이런 종류의 내부 구조에 익숙하지 않습니다.

그러나 그것은 아마도 외부에서 호출되는 함수를 가질 수없는 스크립트 일 것입니다. 그렇다면 변수를 즉시 계산하고 할당하기 시작하기 때문입니다. 함수를 재사용하려고 할 때 새 스크립트가 이전 스크립트와 밀접하게 관련되어 변수가 충돌 할 가능성이 있습니다.

독립 기능을 분리하면 이전 작업을 다른 스크립트로 호출하여 이전 작업을 재사용 할 수 있습니다. 예를 들어, “example.py”는 “xy.py” x()에서 ‘x’함수를 사용하여 “xy.py”를 가져 와서 호출 할 수 있습니다. (어쩌면 주어진 텍스트 문자열의 세 번째 단어를 대문자로 사용하거나, 숫자 목록에서 NumPy 배열을 만들어 제곱하거나, 3D 표면을 비추는 것입니다. 가능성은 무한합니다.)

(여기서, 이 질문 에는 @kindall의 답변 포함되어있어 마침내 이해하는 데 도움이되었습니다. 이유는 방법이 아닌 이유입니다. 불행히도 이것은 실수라고 생각되는 복제본으로 표시되었습니다 .)