완전 기초부터 시작하는 파이썬
모듈은 전역변수, 함수, 클래스 등을 모아놓은 파일이라면, 패키지는 모듈을 디렉토리 형식으로 구조화 한 것이다.
패키지는 . 을 사용해 파이썬 모듈을 계층적으로 관리할 수 있게 해준다.
패키지는 모듈을 넣어둔 디렉토리가 패키지명이 된다.
패키지 내 각 디렉토리에는 __init__.py가 반드시 존재해야 한다.__init__.py는 내용이 비어있을 수도 있고, 패키지 내에 포함된 모듈의 정보를 제공하기도 한다.
예시
# 예시 : game 이라는 패키지
game/
__init__.py
sound/
__init__.py
echo.py
wav.py
graphic/
__init__.py
screen.py
render.py
play/
__init__.py
run.py
test.py
위의 예시로 든 패키지 구조를 간단하게 구성해보면 다음과 같다.
먼저 game디렉토리를 생성하고 그 아래 기타 서브 디렉토리를 생성한다.
그 후 각 디렉토리마다 __init__.py파일을 생성한다.
# echo.py
def echo_test():
print("echo")
# render.py
def render_test():
print("render")
위의 두개의 파일은 현재 sound 디렉토리에 위치한 상태이며 해당 모듈들을 import하는 방법은 다음과 같다
# 방법 1
import game.sound.echo
print(game.sound.echo.echo_test())
# 방법 2
from game.sound import echo
print(echo.echo_test())
# 방법 3
from game.sound.echo import echo_test
print(echo_test())
세가지 방법 모두 아래의 결과로 동일하다.
echo
단, 다음과 같은 방법으로 사용하는 것은 불가능하다.
# 잘못된 방법 1
import game
print(game.sound.echo.echo_test())
# 잘못된 방법 2
import game.sound.echo.echo_test
print()
반드시 . 을 사용해 import a.b.c처럼 import 할 때 가장 마지막 항목인 c는 모듈이거나 패키지여야만 한다.
잘못된 방법 1은 game 디렉토리의 모듈 또는 __init.py__에 정의한 것만 참조 가능하므로 잘못되었다.
잘못된 방법 2은 import a.b.c의 c부분이 모듈이나 패키지가 아니므로 잘못되었다.
__init__.py의 용도__init__.py파일은 해당 디렉토리가 패키지의 일부임을 알려주는 역할을 한다. 만약 패키지에 포함된 디렉토리에 __init__.py 파일이 없으면 패키지로 인식되지 않으며, 없는 상태에서 import 하게되면 다음과 같이 오류가 나타난다.
# __init__.py가 없는 경우 오류
>>> from game.sound import*
>>> echo.echo_test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'echo' is not defiend
python 3.3 버전부터는 __init__.py가 없어도 패키지로 인식하지만 하위버전 호환성을 위해 생성하는 것이 안전하다.
__all__*을 사용하여 import 할 때는 __init__.py파일에 __all__변수를 설정하고 호출할 수 있는 모듈을 정의해줘야 한다.# game/sound/__init__.py
__all__ = ['echo']
위 파일의 의미는 sound 디렉토리에서 *기호를 사용하여 import할 경우 이곳에 정의된 echo모듈만 import된다.
파일수정 후 다시 수행하면 다음과 같이 작동하는 것을 확인할 수 있다.
>>> from game.sound import*
>>> echo.echo_test()
echo
예시 구조의 graphic의 render.py모듈이 sound 디렉토리의 echo.py를 사용하고자 할때는 아래처럼 파일을 수정하면 사용할 수 있게 된다.
# render.py
from game.sound.echo import echo_test
def render_test()
print("render")
echo_test()
첫 번째 줄처럼 import를 하면 다음과 같이 정상작동하는 것을 볼 수 있다.
>>> from game.graphic.render import render_test()
>>> render_test()
rendeo
echo