Python Module & Package: __init__.py와 __main__가 대체 뭐 하는 녀석들이지?

d4v1d·2022년 3월 11일
1

개요

Python module과 package 구조에 대해 이해하고, Python 코드에서 자주 보이는 __init__py와 __main__.py의 의미를 정리한 포스트입니다. 😴

모듈과 패키지

참고자료 - 점프 투 파이썬: 패키지
패키지(Package)는 Python 모듈이 어떤 계층을 가지고 모여있는 모듈의 집합입니다. 하나의 패키지 안에는 여러 개의 모듈이 들어있고, 각 모듈은 하나의 .py 파일입니다. A라는 패키지 안에 들어있는 모듈 B.py를 가리킬 때 A.B로 나타냅니다.

참고 패키지 A, 모듈 B.py, 함수 C() 👉🏻 A.B.C

모듈과 시작점, 그리고 "__main__"

Flask같은 Python 코드를 보면 이런 코드를 자주 접하게 됩니다.

if __name__ == '__main__':
	# ...

다음 예제 코드를 통해 \__name\__\__main\__에 대해 알아봅시다.

hello.py

print('hello 모듈 시작')
print('hello.py __name__:', __name__)    # __name__ 변수 출력
print('hello 모듈 끝')

main.py

import hello    # hello 모듈을 가져옴
 
print('main.py __name__:', __name__)    # __name__ 변수 출력

실행

» python main.py
hello 모듈 시작
hello.py __name__: hello	# 모듈로서 호출되었기 때문에 모듈의 이름이 출력됨!
hello 모듈 끝
main.py __name__: __main__	# main 코드로서 실행되었기 때문에 "__main__"이 출력됨!

따라서 어떤 모듈의 __name__에 저장된 값이 모듈의 이름인지, 혹은 "__main__"인지에 따라 모듈로 사용되었는지 혹은 직접 실행된 코드인지를 알 수 있습니다.
정리하면, Python은 C나 JAVA와는 달리 별도로 main 함수를 지정하지 않고, 어떤 .py 파일이든 프로젝트의 시작 함수가 될 수 있습니다. 그래서 시작 함수로 실행되었는지 여부를 확인하기 위해 __name__을 검사하는 것이죠!

패키지, 그리고 __init__.py

아래 예시와 같은 game이라는 이름의 Python 패키지가 있다고 가정합시다.

game/	# 루트 디렉터리
    __init__.py
    sound/			# 서브 디렉터리
        __init__.py
        echo.py
        wav.py
    graphic/		# 서브 디렉터리
        __init__.py
        screen.py
        render.py
    play/			# 서브 디렉터리
        __init__.py
        run.py
        test.py

__init__.py
해당 디렉터리가 패키지의 일부임을 알려주는 역할을 합니다. 이 파일이 없는 디렉터리는 패키지에 포함이 안 됩니다. Python3.3 이후 버전부터는 __init__.py이 없어도 패키지로 인식하지만, 하위 버전과의 호환을 위해서는 이 파일을 생성하는 것이 안전합니다.

echo.py에 echo_test()라는 함수를 실행하기 위해 패키지 또는 모듈을 import하는 상황을 가정합시다.

# Python interpreter
>>> import game.sound.echo					# 함수를 가지고 있는 패키지 영역을 import하여 함수를 사용
>>> game.sound.echo.echo_test()				# OK
	---
>>> from game.sound import echo				# 모듈을 import하여 함수 사용
>>> echo.echo_test()						# OK
	---
>>> from game.sound.echo import echo_test	# 함수를 직접 import
>>> echo_test()								# OK
	---
	---
>>> import game								# error!
>>> game.sound.echo.echo_test()				# echo_test()는 game/__init__.py에 정의되어 있지 않음 
	---
>>> import game.sound.echo.echo_test		# error!
										# 도트(.) 연산자로 import하는 마지막 항목이 함수임!

import game을 실행하면 game/에 들어있는 __init__.py에 정의된 것만 참조할 수 있습니다. 또한, 도트(.) 연산자를 사용해 import하는 경우 가장 마지막 항목은 반드시 모듈이거나 패키지여야 합니다.

또, 아래처럼 특정
디렉터리의 모듈을 *로 전부 import할 때에는 해당 디렉터리의 __init__.py에 __all__ 변수를 선언하여 import하는 모듈을 정의해야 합니다.

game/sound/__init__.py에 __all__이 정의되지 않은 경우

# Python interpreter
>>> from game.sound import *
>>> echo.echo_test()			# error!

game/sound/__init__.py에 __all__이 정의된 경우

# game/sound/__init__.py
__all__ = ['echo']		# sound라는 디렉터리에서 "*"에 포함될 모듈을 나열!
# Python interpreter
>>> from game.sound import *
>>> echo.echo_test()			# OK

정리

Python 프로젝트나 패키지, 혹은 코드에서 자주 등장하는 __init__.py"__main__"에 대해 살펴보았습니다. 프로그램의 시작점을 알려주는 변수가 "__main__", 패키지의 일부임을 알려주는 파일이 __init__.py입니다. 👾

profile
데이터 엔지니어/백엔드 개발자 d4v1d의 개발 일지🐯

1개의 댓글

comment-user-thumbnail
2024년 9월 15일

As the rounds progressed, Jack’s initial nerves were replaced by confidence. He used a blend of basic strategy and his intuition to make https://winnerwolfcasino.com his decisions. To his delight, his efforts started paying off. He found himself winning hand after hand, each victory fueling his excitement. By the end of the night, Jack had not only enjoyed a thrilling experience but had also managed to double his initial deposit. His first foray into online gambling had turned out to be a memorable and profitable adventure.

답글 달기