이것은 무엇을 하며, 왜 이 if
명령문을 포함해야 합니까?
if __name__ == "__main__":
print("Hello, World!")
이것은 무엇을 하며, 왜 이 if
명령문을 포함해야 합니까?
if __name__ == "__main__":
print("Hello, World!")
의도하지 않은 스크립트를 실수로 호출하지 않도록 사용자를 보호하는 상용구 코드입니다. 다음은 스크립트에서 가드를 생략할 때 발생하는 몇 가지 일반적인 문제입니다.
다른 스크립트(예: )에서 가드리스 스크립트를 가져오는 경우 후자의 스크립트는 가져오기 시 두 번째 스크립트의 명령줄 인수를 사용하여 전자 import my_script_without_a_name_eq_main_guard
를 실행하도록 트리거합니다 . 이것은 거의 항상 실수입니다.
가드리스 스크립트에 사용자 정의 클래스가 있고 이를 피클 파일에 저장한 경우 다른 스크립트에서 이를 언피클링하면 가드리스 스크립트 가져오기가 트리거되며 이전 글머리 기호에서 설명한 것과 동일한 문제가 발생합니다.
이것이 왜 그리고 어떻게 중요한지 더 잘 이해하려면 Python이 스크립트를 초기화하는 방법과 이것이 모듈 가져오기 메커니즘과 상호 작용하는 방법을 이해하기 위해 한 걸음 물러서야 합니다.
Python 인터프리터는 소스 파일을 읽을 때마다 두 가지 작업을 수행합니다.
와 같은 몇 가지 특수 변수를 설정한 __name__
다음
파일에서 찾은 모든 코드를 실행합니다.
__name__
이것이 어떻게 작동하고 Python 스크립트에서 항상 볼 수 있는 검사에 대한 귀하의 질문과 어떻게 관련되는지 봅시다 .
약간 다른 코드 샘플을 사용하여 가져오기 및 스크립트가 작동하는 방식을 살펴보겠습니다. 다음이 라는 파일에 있다고 가정합니다 foo.py
.
# Suppose this is foo.py.
print("before import")
import math
print("before function_a")
def function_a():
print("Function A")
print("before function_b")
def function_b():
print("Function B {}".format(math.sqrt(100)))
print("before __name__ guard")
if __name__ == '__main__':
function_a()
function_b()
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
인터프리터는 파일을 검색하고(몇 가지 다른 변형 검색과 함께) 해당 모듈을 실행하기 전에 import 문에서 변수에 foo.py
이름을 할당합니다."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"
특수 변수가 설정된 후 인터프리터는 모듈의 모든 코드를 한 번에 한 문씩 실행합니다. 이 설명을 따라갈 수 있도록 코드 샘플이 있는 측면에서 다른 창을 열 수 있습니다.
언제나
문자열을 인쇄합니다 "before import"
(따옴표 제외).
모듈을 로드하고 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")
그것은 문자열을 인쇄합니다 "before function_a"
.
블록을 실행하여 def
함수 개체를 만든 다음 해당 함수 개체를 이라는 변수에 할당합니다 function_a
.
그것은 문자열을 인쇄합니다 "before function_b"
.
두 번째 def
블록을 실행하여 다른 함수 개체를 만든 다음 이라는 변수에 할당합니다 function_b
.
그것은 문자열을 인쇄합니다 "before __name__ guard"
.
모듈이 메인 프로그램인 경우에만
__name__
실제로 로 설정되어 "__main__"
있고 두 함수를 호출하여 문자열 "Function A"
및 "Function B 10.0"
.다른 사람이 모듈을 가져온 경우에만
__name__
은 "foo"
, 가 아니며 명령문 "__main__"
의 본문을 건너뛸 것 입니다.if
언제나
"after __name__ guard"
두 상황 모두 에서 문자열을 인쇄합니다 .요약
요약하면 다음은 두 가지 경우에 인쇄되는 내용입니다.
# What gets printed if foo is the main program
before import
before function_a
before function_b
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 function_a
before function_b
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 function_a():
print("a1")
from foo2 import function_b
print("a2")
function_b()
print("a3")
def function_b():
print("b")
print("t1")
if __name__ == "__main__":
print("m1")
function_a()
print("m2")
print("t2")
__name__
이제 체크인 을 제거하면 어떻게 되는지 알아보세요 foo3.py
.# Suppose this is foo3.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
def function_a():
print("a1")
from foo3 import function_b
print("a2")
function_b()
print("a3")
def function_b():
print("b")
print("t1")
print("m1")
function_a()
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__
대신 가 string 으로 설정됩니다 "__main__"
. 따라서 스크립트가 직접 실행되고 있는지 테스트를 통해 다른 것으로 가져오는지 테스트할 수 있습니다.
if __name__ == "__main__":
...
스크립트를 다른 모듈로 가져오는 경우 다양한 함수 및 클래스 정의를 가져오고 최상위 코드가 실행되지만 if
위 절의 then-body에 있는 코드는 조건이 다음과 같이 실행되지 않습니다. 충족시키지 못함. 기본 예제로 다음 두 스크립트를 고려하십시오.
# 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__"
.
다음 두 파일을 만듭니다.
# a.py
import b
# b.py
print("__name__ equals " + __name__)
if __name__ == '__main__':
print("if-statement was executed")
이제 각 파일을 개별적으로 실행하십시오.
실행 중 python a.py
:
$ python a.py
__name__ equals b
가 실행 되면 a.py
모듈을 가져옵니다 b
. 이렇게 하면 내부의 모든 코드 b
가 실행됩니다. Python은 globals()['__name__']
모듈 b
에서 모듈의 이름인 b
.
실행 중 python b.py
:
$ python b.py
__name__ equals __main__
if-statement was executed
파일만 b.py
실행될 때 Python은 globals()['__name__']
이 파일을 "__main__"
. 따라서 if
명령문은 True
이 시간으로 평가됩니다.
[Python] 단일 표현식에서 두 개의 사전을 병합하려면 어떻게 해야 합니까? (0) | 2022.07.31 |
---|---|
[Python] 파일이 예외 없이 존재하는지 어떻게 확인합니까? (0) | 2022.07.31 |
[Python] 파이썬에서 메타클래스란 무엇입니까? (0) | 2022.07.31 |
[Python] Python에 삼항 조건부 연산자가 있습니까? (0) | 2022.07.31 |
[Python] "yield" 키워드는 무엇을 합니까? (0) | 2022.07.31 |