파이썬(python) - if __name__ == "__main__"을 사용하는 이유(Feat. 네임스페이스)
개요
파이썬 공부를 하다 보면 심심치않게 다음과 같은 코드를 볼 수 있습니다.
if __name__ == "__main__":
...
사실 딱히 진입점(C로 따지면 main함수)이랄게 없는 파이썬에서 "굳이 저런걸 써야하나?" 싶었던 분들이 꽤 계실 것 같습니다. 하지만 저 코드는 생각보다 중요한 역할을 맡고 있습니다. 이를 알아보기 전에 먼저 네임스페이스에 대해 알아봅시다.
파이썬에서의 네임스페이스(Namespace)
우리의 영원한 친구이자 동료인 위키백과에서는 네임스페이스가 다음과 같은 뜻이라고 합니다.
개체를 구분할 수 있는 범위
대황신갓키백과
네. 정말 그게 다입니다. 좀 더 풀어서 설명하자면, 어떤 객체를 이름으로 구분할 수 있는 범위를 의미합니다.
여러분도 아시다시피 파이썬에서는 모든 것이 객체입니다. 그리고 그 객체들은 각자의 이름을 가지고 구분할 수 있습니다.
하지만 객체를 이름만 가지고 구분하기엔 많이 아쉽습니다. 만약 그렇다면 모든 함수, 변수, 클래스 등의 이름을 전부 다 다르게 설정해야 하니까요. 그렇게 하는건 일정 규모 이상에선 불가능합니다.
그래서 고통받을뻔한 우리를 구원하기 위해 네임스페이스라는 개념이 존재하는 것입니다. 객체마다 자신의 영향력을 행사할 수 있는 범위를 제한하여 이름의 중복을 허용한 것이죠.
def func1():
name = "심춘자"
def func2():
name = "김갑두"
그래서 우린 위와 같은 코드를 사용할 수 있습니다. func1과 func2의 네임스페이스는 다른 공간이며 따라서 func1의 name을 어떤 값으로 바꿔도 func2의 name에는 영향을 주지 않습니다. 이러한 네임스페이스들은 locals()함수를 통해서 확인 가능합니다.
파이썬에서 네임스페이스는 크게 3가지로 구분됩니다.
1. 지역 네임스페이스(Local namespace) - 함수(메소드)별로 구분되는 네임스페이스
2. 글로벌 네임스페이스(Global namespace) - 모듈 단위로 구분되는 네임스페이스
3. 빌트인 네임스페이스(Built-in namespace) - 내장 함수를 포함한 전체 코드 네임스페이스
어떤 객체를 참조하려고 할 때, 탐색 순서는 지역 -> 글로벌 -> 빌트인 순으로 탐색합니다. 하지만 역순 참조는 불가능합니다.
word = "무야호"
def say():
print(word)
say()
"무야호"
그래서 if __name__ == "__main__" 이건 대체 왜 쓰는거임
저 __name__이라는 친구에겐 신기한 특징이 하나 있습니다.
# test1.py
print(__name__)
# 출력 : __main__
파이썬 파일을 커맨드라인이나 인터페이스를 통해 직접 실행한 경우 __name__에는 __main__이라는 값(네임스페이스)이 설정됩니다.
# test2.py
import test1
print(test1.__name__)
# 출력 : test1
하지만 파이썬 파일을 모듈로서 사용, 즉 다른 파일에서 불러와 사용하는 경우 __name__에는 모듈 이름이 설정됩니다.
정리하자면 if __name__ == "__main__" 은 해당 구문이 사용된 파이썬 파일을 직접 실행했을 때만 아래 코드를 실행하겠다 라는 의미입니다.
이는 파이썬 개발자들이 저지를 수 있는 실수를 막아줍니다.
### test1.py
print("메롱")
### test2.py
import test1
print("ㅎㅇ")
test2.py를 실행하면 어떻게 될까요? 겉으로 보기엔 test1을 임포트만 했으니 아무런 영향이 없을 것 같지만..
메롱
ㅎㅇ
test1에 있던 print문이 출력되는 모습입니다. test1모듈에 아무런 조치를 취하지 않았기에 이런 일이 발생하게 된 것입니다.
### test1.py
if __name__ == "__main__":
print("메롱")
test1모듈에 위와 같이 __name__을 이용한 구문을 넣어주면 모듈이 임포트 되면서 실행되는 참사를 막을 수 있습니다.