TIL 15 | Import Module & Package
sys
Module과 Package를 사용하기 위해 Import하는 경우 Python은 어떻게 Module과 Package를 찾을까? 예를 들어 abc
라는 패키지가 존재한다면, 이를 사용하기 위해 다음과 같이 import한다.
import abc
이 경우 python은 abc라는 패키지가 존재하는 경로를 찾아야 import가 가능하다.
Python은 다음의 3가지 장소를 순서대로 보며 찾는다.
sys.modules
built-in modules
sys.path
sys.modules
sys.modules
는 단순한dictionary
로 이미 import된 모듈이나 패키지를 저장하고 있어 다시 찾지 않아도 되도록 하는 기능을 하고 있다. 따라서 새로 import하는 모듈은sys.modules
에서 찾을 수 없다.
built-in modules
파이썬이 제공하는 공식 라이브러리들로, built-in module들은 이미 파이썬에 포함되어 있어 쉽게 찾을 수 있다.
sys.path
sys.path
는 기본적으로 string 요소들을 가지고 있는 list 이다. 파이썬은 list의 각 경로를 하나하나 확인하며 해당경로에 import 하고자 하는 모듈이나 패키지가 존재하는지 확인한다.
정리를 하자면, 파이썬은 import 하고자 하는 모듈과 package를 찾을때에 먼저 sys.modules
를 보고, 없으면 파이썬 built-in 모듈들을 확인 하고 마지막으로 sys.path
에 지정되어 있는 경로들을 확인해서 찾는다. sys.path 에서도 못찾으면 ModuleNotFoundError
에러를 리턴한다.
sys.modules와 sys.path의 차이점
대체로 각각의 특징을 위에서 살펴보았지만, 중요한 차이텍스트는
sys.modules
은 자료구조가dictionary
이지만sys.path
는string
요소를 가지는list
이다.- import하는 모듈이나 패키지의 경로를 찾을 경우
sys.modules
를 가장 먼저 보고,sys.path
는 가장 나중에 확인한다.
sys의 경로
sys 또한 import해야하는 module이고, 파이썬에 내장되어 있는 built-in module이다. 따라서 파이썬 설치시 기본적으로 경로가 저장되어 있으므로 쉽게 찾을 수 있다.
Absolute Path and Relative Path
파이썬의 built-in module은 경로가 저장되어 있어 import에 문제가 없고, 외부 모듈 및 패키지는 sys.path
에 이미 포함되어 있는 site-packages
라는 디렉토리에 설치되기에 문제가 없다.
그러나 직접 개발한 local package를 import할때에는 해당 package 위치에 맞게 경로를 잘 지정해야 한다. 경로를 지정할 경우 absolute path와 relative path 두 가지 방법이 존재한다.
Absolute path는 프로젝트 폴더 최상위 기준으로 경로가 표시되며, relative path는 import하는 파일 기준으로 경로가 표시된다.
Absolute path는 어느 파일, 어느 위치에서 import하던지 경로가 동일하다. 따라서 파일 위치가 변경되는 경로 위치를 변경할 필요가 없다. 그러나 경로 길이가 길어질 수 있다는 단점이 존재한다.
Relative path는 absolute path와 다르게 프로젝트 최상단 디렉토리 기준이 아니라 import하는 위치를 기준으로 한다고 했으므로 absolute path에 비해 짧은 경로 길이를 가질 수 있어 일반적으로 local package 안의 local package를 import할 경우 자주 사용된다. 경로 길이가 짧은 것이 장점이지만 파일의 변경이 있을 경우 경로 위치도 변경되어야 하는 단점이 있다.
Caculator Package 만들기
Module과 Package를 Import하는 과정을 이해하기 위해 아래와 같은 디렉토리 구조와 코드를 가지는 패키지를 만드는 실습을 해보았다.
Module과 Package를 Import하는 과정을 이해하기 위해 아래와 같은 디렉토리 구조와 코드를 가지는 패키지를 만드는 실습을 해보았다.
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
위와 같은 패키지를 직접 작성하여 main.py에서 relative path로 add_and_multiply.py
를 import하였더니 다음과 같은 에러가 발생하였다.
Traceback (most recent call last):
File "/Users/imjongseong/Desktop/python1/main.py", line 6, in <module>
from .calculator.add_and_multiply import add_and_multiply
ImportError: attempted relative import with no known parent package
Error의 의미를 보면 알려진 parent package가 없다는 것이다. 참고자료를 확인해보니 상대경로를 지정하는 경우 현재 위치 모듈의 이름을 따르는데, main.py
와 같은 메인 모듈의 경우 모듈 이름이 __main__
으로 지정되기에 메인 모듈은 상대경로를 쓸 수 없고 반드시 절대경로를 사용해야 한다는 내용이었다.
따라서 코드를 다음과 같이 바꾸고 실행하였더니 에러가 사라지고 정상적인 결과가 출력되었다.
# 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))
# output : 5
add_and_multiply.py
다음으로 add_and_multiply.py에서 multiply function을 상대경로로 import 해봤고 다음과 같은 에러가 나왔다.
from .multiplication import multiply
#from calculator.multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
print(add_and_multiply(1,2))
Traceback (most recent call last):
File "/Users/imjongseong/Desktop/python1/calculator/add_and_multiply.py", line 1, in <module>
from .multiplication import multiply
ImportError: attempted relative import with no known parent package
마치 main.py
에서 상대경로로 import할때와 같은 결과가 나왔다. 이번에는 절대경로로 import 해봤더니 또 에러가 나왔다.
#from .multiplication import multiply
from calculator.multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
print(add_and_multiply(1,2))
Traceback (most recent call last):
File "/Users/imjongseong/Desktop/python1/calculator/add_and_multiply.py", line 2, in <module>
from calculator.multiplication import multiply
ModuleNotFoundError: No module named 'calculator'
이번에는 calculator
라는 패키지가 존재하지 않는것처럼 결과가 출력되었다. 분명히 add_and_multiply.py
는 calculator
디렉토리 안에 존재하는데, 어떻게 된 일일까? 곰곰히 생각해보니 add_and_multiply.py
가 main.py
같이 메인 모듈 행세를 하고 있는 것 같은 느낌이 들어 main.py
의 경우처럼 절대경로로 import 했더니 정상 출력이 되었다.
from multiplication import multiply
#from calculator.multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
print(add_and_multiply(1,2))
# output : 5
분명히 main.py
에서 add_and_multiply
function을 import 했을때 정상적으로 작동한 것을 봤는데 실제로 add_and_multiply.py
에서는 절대경로, 상대경로 둘 다 에러가 발생한 것을 볼 수 있었다.
곰곰히 생각해보니 main.py
에서 import할 경우는 모듈로써 실행한 것이지 직접 파일로 실행한 것이 아니었다. 하지만 add_and_multipy.py
에서 실행한 경우 모듈로써 실행한 것이 아니라 직접 실행했기에 메인 모듈 취급을 받았다. 그렇기에 자기가 속한 calculator
패키지가 존재하지 않는 것처럼 행동하고, 상대경로 또한 사용할 수 없던 것이다.
init
init.py는 자신이 위치한 디렉토리가 패키지의 일부임을 확인해주는 역할을 한다. python의 버전 3.3부터는 init.py 파일이 없어도 패키지를 인식하도록 업데이트되었다고 한다. 하지만 하위 호환을 위해 init.py를 생성하는 것이 안전하다.
Author And Source
이 문제에 관하여(TIL 15 | Import Module & Package), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hkja0111/TIL-15-Import-Module-Package저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)