파이썬 패키지(Package)
1. 패키지(Package)
- 패키지 : 모듈을 기능별 묶음으로 묶어놓은 단위
*모듈 : 코드를 작은 단위로 나눠서 저장해 놓은 파일
- 패키지를 사용함을 통해 프로그램의 구성요소를 잘 정리할 수 있으며, 쉽게 재활용이 가능하다.
2. 패키지의 구성
- 패키지는 기본적으로 디렉토리 단위이며, 내부에 __init__.py, 그리고 사용될 모듈들로 구성된다.
shapes/
__init__.py
area.py
volume.py
run.py
- 패키지를 불러올 땐 모듈과 동일하게 import를 사용한다.
패키지 호출 → import 패키지명
import shapes
그러나 위와 같이 패키지를 불러올 경우, 파이썬에서는 패키지 내에 있는 모듈들은 가져올 수 없다.
* __init__.py (init : 초기화, initialize)
▶ 패키지를 초기화 할 때 사용되는 파일이며, 모듈을 import하면 동시에 같이 실행된다.
이러한 성격이 있기 때문에, 패키지 안에 있는 모듈들을 __init__.py파일에서 호출하게되면,
위의 'import shapes'와 같은 호출만으로도 패키지 내에 있는 모듈들을 가져올 수 있다.
▼ __init__.py에서 모듈로 불러오기
# __init__.py
from shapes import area, volume
# run.py
import shapes
print(shapes.area.square(2))
print(shapes.volume.cube(2))
>>> 4
>>> 8
▼ __init__.py에서 함수로 불러오기 (*run.py에서 모듈명 없이 함수명만으로 호출이 가능)
# __init__.py
from shapes.area import circle, square
# run.py
import shapes
print(shapes.circle(2))
print(shapes.square(2))
>>> 12.56
>>> 4
▶ 여러 모듈에서 사용되는 변수 또한 __init__.py에서 호출하면 동일하게 사용이 가능하다.
▶ 파이썬 3.3ver 이전에는 __init__.py 파일이 필수로 있어야 import 할 수 있었다.
현재는 필수는 아니지만, 호환성을 위해 __init__.py를 만들어주는 것을 권장한다.
* 특수변수 __all__
▶ __init__.py에서 import *를 하였을 때에는 '__00__'과 같은 변수들만 import 된다.
# run.py
from shape import *
print(dir())
>>> ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
import *를 했을 때 다른 변수들을 가져오기 위해서 특수변수 __all__을 사용하면 된다.
사용방법은 아래와 같이 가져와야 할 정보들을 리스트에 문자열로 넣어서 사용한다.
▼ 각 모듈에서 __all__을 정의하는 경우
# shapes/area.py
# __all__ 정의
__all__ = ['circle', 'square']
PI = 3.14
# 원의 면적을 구해 주는 함수
def circle(radius):
return PI * radius * radius
# 정사각형의 면적을 구해 주는 함수
def square(length):
return length * length
run.py를 실행하면 아래와 같이 'circle'와 'square'가 추가된 것을 확인할 수 있다.
# run.py
from shapes.area import *
print(dir())
>>> ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'circle', 'square']
▼ __init__.py에서 __all__을 정의하는 경우 (모듈 자체를 불러옴)
# __init__.py
__all__ = ['area', 'volume']
run.py를 실행하면 아래와 같이 'area'와 'volume'이 추가된 것을 확인할 수 있다.
# run.py
from shape import *
print(dir())
>>> ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'area', 'volume']
모듈 호출 → import 패키지명.모듈명 (as 별칭)
# 방법 1
import shapes.volume as vol
# 방법 2
from shapes import volume
함수 호출 → 패키지명.모듈명.함수명
## 모듈 import, alias 미사용시
import shapes.volume
shapes.volume.cube(3)
## 모듈 import, alias 사용시
import shapes.volume as vol
vol.cube(3)
## 함수 직접 호출
from shape.area import square
square(3)
3. 서브 패키지
- 패키지 안에 또 다른 패키지가 있을 경우, 안에 있는 패키지를 서브패키지라고 말한다.
mymath/
shapes/
__init__.py
area.py
volume.py
stats/
__init__.py
average.py
spread.py
__init_.py
run.py
여기서 shape 패키지와 stats 패키지는 서브패키지라고 할 수 있다.
4. Import
- 구조가 복잡할 경우 import를 제대로 하지 않으면 한참을 고민하게 되니 아래를 잘 숙지해야 한다.
(1) import ...
# 패키지 임포트
import mymath
# 서브패키지 임포트
import mymath.shapes
# 모듈 임포트
import mymath.shapes.area
# 모듈 안에 있는 변수나 함수는 이 방식으로 임포트 할 수 없음
import mymath.shapes.area.circle # 오류
- import 뒤에 호출할 모듈이나 패키지를 써준다. 그러나 모듈 안에 있는 변수나 함수는 이 방식으로 호출이 불가하다.
- 또, (서브)패키지를 호출할 때에는 임포트할 대상을 (서브)패키지의 __init__.py에 입력해두어야 한다.
2) from ... import ...
# 패키지 안에 있는 패키지 임포트
from mymath import shapes
# 패키지 안에 있는 모듈 임포트
from mymath.shapes import area
# 모듈 안에 있는 함수 임포트
from mymath.shapes.area import circle
# import 뒤에는 . 을 쓸 수 없음
from mymath import shapes.area # 오류
- from 뒤에는 모듈이나 패키지, import 뒤에는 모듈이나 패키지 내부에서 호출할 대상을 써준다.
- 주의할 점은 import 뒤에는 4번째 문처럼 '.'을 쓰게되면 오류가 난다.
5. 상대경로
- 패키지를 import할 때 상대경로를 사용하면 더 간단하게 코드를 짤 수 있다.
mymath/
shapes/
__init__.py
area.py
volume.py
stats/
__init__.py
average.py
spread.py
__init_.py
run.py
- 상대경로는 위치에 따라 아래와 같이 '.' 과 '..' 2가지로 사용이 가능하다.
# 현재 경로
from . import *
# 상위 경로
from .. import *
- 위 경로의 shapes내에 있는 __init__.py에서 mymath.shapes 패키지를 불러올 경우 아래와 같이 변경이 가능하다.
# 기존(절대경로)
from mymath.shapes import area, volume
# 변경(상대경로)
from . import area, volume
- 함수를 가져올 경우에도 마찬가지로 사용이 가능하다.
# 기존(절대경로)
from mymath.shapes.area import *
from mymath.shapes.volume import *
# 변경(상대경로)
from .area import *
from .volume import *
# 기존(절대경로)
from mymath.stats.average import data_mean
# 변경(상대경로)
from ..stats.average import data_mean
- 상대경로는 코드가 간소화되지만 직관성이 떨어지고 패키지 구조가 어떻게 되는지 파악하기 힘든 단점이 있으므로,
경로가 너무 복잡해지는 경우에는 절대경로로 입력하는 것이 좋다.
'DEV > 파이썬 이론' 카테고리의 다른 글
파이썬 코딩 :: 파이썬 문법, 계산기 만들기_TIL#07 (0) | 2022.09.06 |
---|---|
파이썬 코딩 :: 파이썬 외부 패키지 (0) | 2022.09.06 |
파이썬 코딩 :: 파이썬 문법, 효율적인 코딩 공부법_TIL#06 (4) | 2022.09.05 |
파이썬 코딩 :: 파이썬 모듈(Module) (0) | 2022.09.05 |
파이썬 코딩 :: 파이썬 문법, 알고리즘_TIL#05 (0) | 2022.09.02 |
댓글