패키지(packages)
: 도트(.)를 사용하여 파이썬 모듈을 계층적(디렉터리 구조)으로 관리할 수 있게 해준다.
ex) 모듈 이름이 A.B인 경우에 A는 패키지 이름, B는 A패키지의 B모듈이 된다.
모듈(modules)
: 파이썬에서 모듈은 하나의 .py 파일이다.
sys는 파이썬에서 제공하는 모듈로, os모듈안에 있으며 파이썬 인터프리터가 제공하는 변수와 함수를 직접 제어할 수 있게 해주는 모듈입니다. C언어로 작성되어 있고 sys는 built-in 되어 있으므로 bulit-in modules에서 찾을 수 있습니다.
파이썬은 다음 3가지 장소를 순서대로 보면서 module/package를 찾습니다.
1. sys.modules
2. built-in modules
3. sys.path
따라서 파이썬은 import하고자 하는 모듈과 package를 찾을때 먼저
sys.modules
를 보고, 없으면 파이썬built-in modules
들을 확인하고 마지막으로sys.path
에 지정되어 있는 경로들을 확인해서 찾습니다.
결국 못찾으면ModuleNotFoundError
에러를 리턴합니다.
'sys':<module 'sys' (built-in)>
-> sys모듈은 이미 built-in 되어 있기 때문에 built-in modules에서 찾게 됩니다.
파이썬의 built-in modules
과 pip
을 통해 설치한 외부 모듈 및 package는 일반적으로 import 하는데 큰 문제가 되지 않습니다.
built-in 모듈은 당연히 잘 찾아지고, pip으로 설치한 외부 모듈도 자동으로 site-packages
라는 디렉토리에 설치가 되는데, 이 site-packages는 sys.path
에 이미 포함되어 있기 때문에 찾는데 문제가 없습니다.
문제는 직접 개발한 local package입니다. 직접 개발한 local package를 import할 때는 해당 package의 위치에 맞게 import 경로를 잘 선언해야 합니다.
sys.path
에 포함되게 됩니다.# Absolute path를 사용해 package1 과 package2를 import
from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1.module5 import function2
# relative path를 사용해package2의 module3에서 package2의 class1과
# package2의 하위 package인 subpackage1의 module5의 function2 함수를 import
from . import class1
from .subpackage1.module5 import function2
# subpackage1/module5.py
from ..module4 import class4
.
은 import가 선언되는 파일의 현재 위치,
..
은 현재위치에서 상위 디렉토리로 가는 경로입니다.
-> 웬만한 경우 absolute path 사용 권장
ImportError: attempted relative import with no known parent package
ImportError
가 발생한다. 파이썬에서 메인 모듈은 항상 절대경로를 이용하여 import 해야한다.
메인 모듈은 패키지의 메인 파일이며, 프로그램의 시작점을 말한다.
메인 모듈에는 if __name__ == "__main__"
코드를 넣어준다.
따라서 메인 모듈은 절대경로로 모듈을 불러와야 한다.
from calculator.add_and_multiply import add_and_multiply
# 상대경로
from .multiplication import multiply
ImportError: attempted relative import with no known parent package
__main__
이 된다. # 절대경로
from calculator.multiplication import multiply
ModuleNotFoundError: No module named 'calculator'
from multiplication import multiply
from .multiplication import multiply
from calculator.multiplication import multiply
__init__.py
파일의 역할init 파일은 해당 디렉토리가 패키지임을 알려주는 역할을 합니다.
특정 디렉토리의 모듈을 *
을 사용하여 import할 때는 해당 디렉토리의 __init__.py
에 __all__
변수를 설정하여 불러오고 싶은 모듈을 정의해주어야 합니다.