디렉토리 구조는 다음과 같다.
패키지 구성
main.py
# absoulte path
#from calculator.add_and_multiply import add_and_multiply
# relative path
from .calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(add_and_multiply(1,2))
add_and_multiply.py
from .multiplication import multiply
# from calculator.multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
multiplication.py
def multiply(a,b):
return(a*b)
각 파일에 해당 코드를 입력하고 main.py에서 상대경로로 add_and_mutiply 를 import했을 때 다음과 같은 에러가 발생한다.
File "/Users/jmin/Desktop/ calculator/main.py", line 5, in <module>
from .calculator.add_and_multiply import add_and_multiply
ImportError: attempted relative import with no known parent package
부모 패키지가 정의되지 않은 상태에서 상대경로로 import해서 발생한 에러이다.
relative imports는 현재 모듈의 이름을 기반으로한다. 기본 모듈의 이름은 always "__main__"이므로 Python 애플리케이션의 기본 모듈로 사용하려는 모듈은 항상 absolute imports를 사용해야한다.
위 내용을 참고하여 절대경로로 변경하여 오류해결 후 결과 출력해보기.
# main.py
# absoulte path
from calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(add_and_multiply(1,2))
출력결과 5
절대경로
from calculator.multiplication import multiply
def add_and_multiply(a,b):
return multiply (a,b) + (a+b)
출력결과 5
상대경로
from .multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
출력결과 5
add_and_multiply.py는 main.py가 아니기 때문에 절대경로든 상대경로든 문제없이 동작한다.
init.py 파일은 해당 디렉터리가 패키지의 일부임을 알려주는 역할을 한다.
만약 add_and_multiply.py와 multiplication.py 패키지에 포함된 디렉터리에 init.py 파일이 없다면 패키지로 인식되지 않는다.
패키지를 읽어 들일 때 init.py를 가장먼저 실행한다.
따라서 패키지를 초기화하는 역할을 한다. 즉, import로 패키지를 가져오면 init.py 파일이 실행되므로 이 파일에서 from . import 모듈 형식으로 현재 패키지에서 모듈을 가져오게 만들어야 한다.
__init__.py
에서는 __all__
이라는 이름의 리스트를 만드는데, 이 리스트에 지정한 모듈들이 from<패키지 이름>import*
를 할 때 전부 읽어 들여진다.