프로그래밍 언어/C++

__name__ == “__main__”: 하면 어떻게 될까?

Rateye 2021. 7. 2. 10:38
728x90
반응형

 

질문 : __name__ ==“__main__”:하면 어떻게됩니까?

다음 코드가 주어지면 if __name__ == "__main__": do?

# 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))
                                                
답변

사용자가 의도하지 않았을 때 실수로 스크립트를 호출하지 못하도록 보호하는 상용구 코드입니다. 다음은 스크립트에서 가드가 생략 될 때 발생하는 몇 가지 일반적인 문제입니다.

  • 가드리스 스크립트를 다른 스크립트 (예 : import my_script_without_a_name_eq_main_guard )로 가져 오면 두 번째 스크립트가 첫 번째 스크립트가 가져 오기시 실행되고 두 번째 스크립트의 명령 줄 인수를 사용하도록 트리거합니다. 이것은 거의 항상 실수입니다.
  • 가드리스 스크립트에 사용자 정의 클래스가 있고이를 피클 파일에 저장 한 경우 다른 스크립트에서이를 언 피클하면 이전 글 머리 기호에서 설명한 것과 동일한 문제가있는 가드리스 스크립트 가져 오기가 트리거됩니다.

 

 

이것이 왜 그리고 어떻게 중요한지 더 잘 이해하려면 파이썬이 스크립트를 초기화하는 방법과 이것이 모듈 가져 오기 메커니즘과 상호 작용하는 방법을 이해하기 위해 한 걸음 물러서야합니다.

Python 인터프리터는 소스 파일을 읽을 때마다 두 가지 작업을 수행합니다.

  • __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 인터프리터가 소스 파일을 읽을 때 먼저 몇 가지 특수 변수를 정의합니다. 이 경우 __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 파일 (몇 가지 다른 변형 검색과 함께)을 검색하고 해당 모듈을 실행하기 전에 import 문에서 "foo" __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" 문자열을 인쇄합니다.

 

모듈이 메인 프로그램 인 경우에만

다른 사용자가 모듈을 가져온 경우에만

항상

요약

요약하면 두 가지 경우에 인쇄되는 내용은 다음과 같습니다.

# 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.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
                                                                
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")
                                                                                                          
                                                                                                          
  • foo3.py __name__ 체크를 제거하면 어떻게되는지 알아 내십시오.
# Suppose this is foo3.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
                                                                                                          
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")
출처 : https://stackoverflow.com/questions/419163/what-does-if-name-main-do
728x90
반응형