일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 빅데이터
- 프로그래밍언어
- 자바스크립트
- 컴퓨터공학
- 데이터베이스
- 보안
- 컴퓨터비전
- 웹개발
- 파이썬
- 데이터과학
- 인공지능
- 사이버보안
- 2
- I'm Sorry
- 알고리즘
- 데이터분석
- 머신러닝
- 자료구조
- 코딩
- 딥러닝
- 클라우드컴퓨팅
- 소프트웨어공학
- 소프트웨어
- 네트워크
- 컴퓨터과학
- Yes
- 버전관리
- 데이터구조
- 네트워크보안
- 프로그래밍
- Today
- Total
스택큐힙리스트
if __name__ == "__main__":가 하는 일은 무엇인가요? 본문
이게 뭐하는 거고, 왜 "if" 문장을 써야 할까요?
"if __name__ == "__main__":
print("Hello, World!")
"
만약 누군가 이 용어를 사용해야하지만 그렇지 않은 문제를 닫으려고한다면, 대신 "Why is Python running my module when I import it, and how do I stop it?" 의 복제를 닫는 것을 고려하십시오. 함수를 호출하지 않은 질문이나 자동으로 입력 지점으로 사용되는 함수의 이름이 "main" 인 것으로 잘못 예상하는 경우 "Why doesn't the main() function run when I start a Python script? Where does the script start running?" 을 사용하십시오.
답변 1
짧은 대답
사용자가 의도하지 않은 경우 스크립트를 부르는 것을 방지하는 보일러플레이트 코드입니다. 스크립트에서 가드가 생략될 때 종종 발생하는 일반적인 문제들을 살펴보겠습니다.
만약 다른 스크립트 (예: "import my_script_without_a_name_eq_main_guard")에 가드가 없는 스크립트를 가져오면, 나중에 스크립트에서 전자가 가져올 때 전자가 후자를 실행시키고 후자의 명령행 인수를 사용합니다. 이것은 거의 항상 실수입니다.
가드 없는 스크립트에서 커스텀 클래스를 가지고 있고 이를 pickle 파일로 저장하면, 다른 스크립트에서 unpickle하면 이전 항목에서 설명한 문제와 동일하게 가드 없는 스크립트를 import하게 됩니다.
장문 답변
이것이 왜 중요하며 어떻게 영향을 미치는지 더 잘 이해하기 위해, 우리는 Python이 스크립트를 초기화하는 방법과 이것이 모듈 가져오기 메커니즘과 상호 작용하는 방법을 이해하기 위해 한 걸음 물러서야 합니다.
파이썬 인터프리터가 소스 파일을 읽을 때마다 두 가지 작업을 수행합니다.
"__name__"와 같은 몇 가지 특수 변수를 설정합니다.
그것은 파일에서 찾은 모든 코드를 실행합니다.
이것이 어떻게 작동하는지, 그리고 파이썬 스크립트에서 항상 볼 수 있는 "__name__" 체크와 어떻게 관련되는지 보겠습니다.
코드 샘플
수입과 스크립트가 어떻게 작동하는지 살펴보기 위해 약간 다른 코드 샘플을 사용해 봅시다. 다음이 "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")
"
특수 변수
파이썬 인터프리터가 소스 파일을 읽을 때, 먼저 몇 가지 특별한 변수를 정의합니다. 이 경우에 우리는 "__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"
"
모듈 코드 실행하기
특수 변수가 설정된 후에 인터프리터는 모듈의 모든 코드를 한 문장씩 실행합니다. 이 설명을 따라가기 위해 코드 샘플이 있는 새 창을 열어 볼 수도 있습니다.
언제나
그것은 문자열 ""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__"이(가) ""__main__""이(가) 아니라 ""foo""가됩니다. 그리고 "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
"
왜 이러한 방식으로 동작하는 걸까요?
당신은 자연스럽게 왜 누구든 이것을 원할까 궁금해 할 수도 있습니다. 하지만 때때로, 다른 프로그램이나 모듈에서 모듈로 사용할 수 있으며 동시에 메인 프로그램으로 실행될 수 있는 #### 파일을 작성하고 싶을 때가 있습니다. 예시:
당신의 모듈은 라이브러리지만, 일부 단위 테스트 또는 데모를 실행하는 스크립트 모드를 가지고 싶습니다.
당신의 모듈은 메인 프로그램으로만 사용됩니다. 하지만 몇 가지 단위 테스트가 있으며, 테스트 프레임워크는 스크립트와 같은 파일을 가져와 특수 테스트 함수를 실행하여 작동합니다. 모듈을 가져오기 때문에 스크립트를 실행하려고 할 필요는 없습니다.
당신의 모듈은 대부분 메인 프로그램으로 사용되지만, 고급 사용자를 위한 프로그래머 친화적인 API도 제공합니다.
그러한 예시 이외에도, 파이썬에서 스크립트를 실행하는 것은 마법 변수 몇 개를 설정하고 스크립트를 가져오는 것으로 간단하게 이루어집니다. 스크립트를 "실행"하는 것은 스크립트 모듈을 가져오는 부작용입니다.
생각거리 식품
질문: 여러 개의 "__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__" 검사를 제거하면 어떻게 될지 알아보세요.
"# 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")
"
답변 2
if __name__ == "__main__": 는 파이썬에서 매우 중요한 표현 중 하나입니다. 파이썬 코드는 일반적으로 모듈 단위로 작성됩니다. 모듈을 정의하고 다른 파일에서 import하여 사용할 수 있습니다. 그러나 때로는 모듈을 직접 실행해야 하는 경우도 있습니다. 이때 if __name__ == "__main__": 는 모듈이 직접 실행될 때 실행할 코드를 작성하기 위해 사용됩니다.
이 표현의 의미는 다음과 같습니다. 파이썬 인터프리터는 __name__ 이라는 특별한 변수를 모든 모듈에 제공합니다. 이 변수는 현재 모듈의 이름을 나타냅니다. 이 변수를 이용해서 현재 모듈이 직접 실행되었는지(import 되었는지)를 확인할 수 있습니다. 따라서 if __name__ == "__main__": 은 현재 모듈이 직접 실행되었을 때만 실행되는 코드를 작성하는데 사용됩니다.
이 표현의 가장 큰 장점은 모듈을 import 할 때 실행되는 코드와 모듈을 직접 실행할 때 실행되는 코드를 분리시킬 수 있다는 것입니다. 예를 들어, 다음과 같은 코드를 생각해 봅시다.
def main():
print("Hello World!")
main()
위 코드는 모듈을 import할 때마다 "Hello World!" 라는 메시지를 출력합니다. 이러한 동작은 모듈을 호출하는 작업에서도 발생할 수 있으며, 이 경우 우리는 이 작업에 별로 관심이 없습니다. 따라서 우리는 이 코드를 다음과 같이 변경할 수 있습니다.
def main():
print("Hello World!")
if __name__ == "__main__":
main()
이제 이 코드는 모듈을 import할 때는 실행되지 않고 모듈을 직접 실행할 때만 "Hello World!" 라는 메시지가 출력됩니다.
위와 같은 이유로, if __name__ == "__main__": 는 파이썬에서 매우 중요하며, 모든 파이썬 프로그래머가 알아야 하는 표현 중 하나입니다.