목차
1. 패키지란?
2. 패키지 만들기
3. 패키지 안의 함수 실행하기
4. __init__.py 파일의 용도
__all__5. 상대경로 패키지
패키지(Package) 는 관련 있는 여러 모듈을 하나로 묶어 관리하는 방법이다.
앞에서 배운 모듈은 하나의 .py 파일이었다.
모듈 → 하나의 .py 파일
패키지 → 여러 모듈을 디렉터리 구조로 관리
예를 들어 게임 프로그램을 만든다고 하면 다음과 같이 구성할 수 있다.
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
sound
graphic
play
는 디렉터리이고
echo.py
wav.py
screen.py
render.py
run.py
test.py
는 모듈이다.
즉,
game 패키지
├─ sound
│ ├─ echo.py
│ └─ wav.py
│
├─ graphic
│ ├─ screen.py
│ └─ render.py
│
└─ play
├─ run.py
└─ test.py
처럼 관련된 모듈을 기능별로 나누어 관리할 수 있다.
패키지 = 관련 있는 여러 모듈을 디렉터리 구조로 관리하는 것
다음과 같은 패키지를 만들어 보자.
C:/doit/game/
__init__.py
sound/
__init__.py
echo.py
graphic/
__init__.py
render.py
echo.py
def echo_test():
print("echo")
render.py
def render_test():
print("render")
__init__.py각 디렉터리에
__init__.py
파일을 만들어 둔다.
예를 들면
game/
__init__.py
sound/
__init__.py
echo.py
처럼 구성한다.
__init__.py는 패키지와 관련된
등을 작성할 때 사용한다.
파이썬에서 패키지를 찾을 수 있도록 경로를 지정할 수도 있다.
Windows
set PYTHONPATH=C:/doit
맥 / 리눅스
export PYTHONPATH=~/doit
PYTHONPATH는 파이썬이 모듈이나 패키지를 찾을 때 참고할 검색 경로라고 생각하면 된다.
패키지 안의 함수를 사용하는 방법은 여러 가지가 있다.
현재 구조가 다음과 같다고 하자.
game/
sound/
echo.py
echo.py
def echo_test():
print("echo")
import game.sound.echo
사용
game.sound.echo.echo_test()
실행 결과
echo
구조를 보면
game
↓
sound
↓
echo
↓
echo_test()
이다.
from ~ import 사용from game.sound import echo
사용
echo.echo_test()
실행 결과
echo
echo 모듈을 직접 가져왔으므로 앞에
game.sound
를 붙이지 않아도 된다.
from game.sound.echo import echo_test
사용
echo_test()
실행 결과
echo
함수 자체를 가져왔기 때문에 가장 짧게 사용할 수 있다.
| 방법 | 사용 |
|---|---|
import game.sound.echo | game.sound.echo.echo_test() |
from game.sound import echo | echo.echo_test() |
from game.sound.echo import echo_test | echo_test() |
import game.sound.echo.echo_test
import a.b.c 형태에서 마지막 c는 일반적으로 모듈이나 패키지여야 한다.
하지만 echo_test는 모듈이 아니라 함수이다.
따라서 함수를 직접 가져오려면
from game.sound.echo import echo_test
처럼 사용한다.
__init__.py 파일의 용도__init__.py는 패키지와 관련된 설정이나 초기화 코드를 작성할 수 있는 파일이다.
예를 들어
game/
__init__.py
가 있다고 해보자.
__init__.py에는
__all__등을 작성할 수 있다.
game/__init__.py
VERSION = 3.5
def print_version_info():
print(f"The version of this game is {VERSION}.")
이제 game 패키지를 불러온다.
import game
변수 사용
print(game.VERSION)
실행 결과
3.5
함수 사용
game.print_version_info()
실행 결과
The version of this game is 3.5.
즉 __init__.py에 작성한 내용은 패키지 수준에서 사용할 수 있다.
__init__.py에서 다른 모듈의 함수를 미리 import할 수도 있다.
game/__init__.py
from .graphic.render import render_test
이제
import game
만 한 뒤
game.render_test()
처럼 사용할 수 있다.
실행 결과
render
원래라면
from game.graphic.render import render_test
를 해야 했지만 __init__.py에서 미리 import했기 때문에 간단하게 사용할 수 있다.
.의 의미from .graphic.render import render_test
여기서 앞의
.
은 현재 패키지를 의미한다.
즉
.game
이라고 생각하는 것이 아니라 현재 위치에서 graphic을 찾는 것이다.
패키지를 처음 불러올 때 자동으로 실행할 코드도 작성할 수 있다.
game/__init__.py
print("Initializing game ...")
이제
import game
을 실행하면
Initializing game ...
이 출력된다.
즉 game 패키지를 처음 import할 때 __init__.py의 코드가 실행된다.
이러한 기능을 이용하면
설정 불러오기
데이터 초기화
환경 설정
공통 변수 생성
등의 작업을 수행할 수 있다.
파이썬은 한 번 import한 모듈이나 패키지를 메모리에 저장해 둔다.
따라서 같은 실행 환경에서
import game
import game
처럼 다시 import한다고 해서 초기화 코드가 계속 반복 실행되는 것은 아니다.
__all__다음과 같이 사용한다고 해보자.
from game.sound import *
*은 모든 것을 가져오겠다는 의미이다.
그런데 패키지 안의 어떤 모듈을 가져올 것인지 명확하게 지정하고 싶다면 __all__을 사용할 수 있다.
game/sound/__init__.py
__all__ = ["echo"]
이제
from game.sound import *
을 실행하면 echo를 사용할 수 있다.
echo.echo_test()
실행 결과
echo
__all__의 역할__all__ = ["echo"]
는
from game.sound import *을 사용할 때echo를 공개하겠다.
라는 의미로 이해하면 된다.
여러 개를 지정할 수도 있다.
__all__ = ["echo", "wav"]
패키지 내부에서 다른 모듈을 가져올 때 전체 경로를 사용할 수 있다.
현재 구조
game/
sound/
echo.py
graphic/
render.py
render.py에서 echo.py의 echo_test()를 사용한다고 해보자.
render.py
from game.sound.echo import echo_test
def render_test():
print("render")
echo_test()
사용
from game.graphic.render import render_test
render_test()
실행 결과
render
echo
여기서
from game.sound.echo import echo_test
처럼 패키지의 처음부터 전체 경로를 작성하는 방식을 절대경로라고 생각하면 된다.
같은 코드를 다음과 같이 작성할 수도 있다.
from ..sound.echo import echo_test
def render_test():
print("render")
echo_test()
여기서
..
은 부모 디렉터리를 의미한다.
render.py의 위치는
game/graphic/render.py
이다.
현재 위치 기준으로 보면
game/
│
├─ sound/
│ └─ echo.py
│
└─ graphic/
└─ render.py ← 현재 위치
render.py가 속한 graphic에서 한 단계 위로 올라가면
game
이 된다.
따라서
from ..sound.echo import echo_test
는
현재 graphic
↓
.. → game으로 이동
↓
sound
↓
echo
↓
echo_test
의 의미이다.
.과 ..| 표현 | 의미 |
|---|---|
. | 현재 디렉터리 |
.. | 부모 디렉터리 |
예를 들어
from .render import render_test
는 현재 패키지의 render 모듈을 의미한다.
from ..sound.echo import echo_test
는 부모 패키지로 이동한 뒤 sound.echo 모듈을 찾는 것이다.
| 구분 | 설명 | 예 |
|---|---|---|
| 모듈 | 하나의 파이썬 파일 | echo.py |
| 패키지 | 여러 모듈을 디렉터리 구조로 관리 | game |
__init__.py | 패키지 초기화 및 설정 | game/__init__.py |
쉽게 생각하면
패키지
↓
폴더
모듈
↓
.py 파일
함수 / 클래스
↓
.py 파일 안의 기능
이다.
예를 들어
game.sound.echo.echo_test()
를 분리해 보면
game → 패키지
sound → 하위 패키지
echo → 모듈
echo_test() → 함수
이다.
| 문법 | 설명 |
|---|---|
import game.sound.echo | 패키지 내부 모듈 import |
from game.sound import echo | 특정 모듈 import |
from game.sound.echo import echo_test | 특정 함수 import |
__init__.py | 패키지 초기화 및 설정 |
__all__ | import *에서 공개할 항목 지정 |
. | 현재 패키지 |
.. | 부모 패키지 |
PYTHONPATH | 파이썬의 모듈 검색 경로 추가 |
패키지는 여러 모듈을 폴더처럼 묶어서 관리하는 방법이다.
전체 구조를 한 번에 보면
game/ ← 패키지
│
├─ __init__.py
│
├─ sound/ ← 하위 패키지
│ ├─ __init__.py
│ └─ echo.py ← 모듈
│ └─ echo_test() ← 함수
│
└─ graphic/ ← 하위 패키지
├─ __init__.py
└─ render.py ← 모듈
└─ render_test() ← 함수
그리고 이번 챕터에서 특히 기억해야 할 것은 다음 3가지이다.
1. 모듈 = .py 파일
2. 패키지 = 여러 모듈을 묶은 디렉터리 구조
3. . = 현재 위치 / .. = 부모 위치