파이썬은 어떻게 import로 module과 package를 찾을까?

Taeha Kim·2020년 7월 30일
1

python

목록 보기
2/3

1. 파이썬은 어떻게 import로 module과 package를 찾을까?

파이썬에서 모듈이나 패지키를 불러올려면 import를 해야합니다.(예: import numpy as np)
파이썬이 모듈과 패키지의 위치를 찾을때, 찾는 순서가 있는데, 순서는 다음과 같습니다.

1.1) sys.modules

파이썬이 모듈이나 패키지를 찾을때 가장 먼저 확인하는곳으로 이미 import한 모듈이나 패키지들을 딕셔너리 자료형으로 저장하는 곳입니다.

1.2) built-in modules

built-in(빌트인)의 사전적인 뜻은

여기서는 "내장된"의 뜻과 가장 비슷한거 같습니다.
모듈,패키지를 sys.modules에서 찾아보고, 없으면 built-in modules에서 찾아보는데
built-in modules는 파이썬에서 제공하는 파이썬 표준 라이브러리들 입니다.
- 파이썬 표준 라이브러리 -

1.3) sys.path

모듈 또는 패키지를 sys.modules과 built-in modules에서 찾아보고도 없을경우, 파이썬은sys.path에서 모듈,패키지를 찾습니다. sys.path는 문자열 요소를 가지고 있는 리스트 자료형으로 되어 있습니다.

import sys
print(sys.path)

실행결과
['/home/kim/wecode/python', 
'/home/kim/miniconda3/lib/python38.zip', 
'/home/kim/miniconda3/lib/python3.8', 
'/home/kim/miniconda3/lib/python3.8/lib-dynload', 
'/home/kim/miniconda3/lib/python3.8/site-packages']

리스트의 요소를 하나씩 확인하면서 해당 경로에 import할 모듈과 패키지를 찾습니다.
만약, sys.path 에서도 못찾으면 ModuleNotFoundError 에러를 리턴합니다.

2. Absolute path와 Relative path의 차이점은?

2.1) Absolute path


Absolute path는 상위 디렉토리에서 부터 모듈이나 패키지가 있는 경로까지 순서대로 지정해주는 방법입니다.
예를들어서 my_app 이라는 프로젝트에서 module5안의 function2를 import한다면, 다음과 같이 사용합니다.

from package2.subpackage1.module5 import function2

2.2) Relative path

Relative path는 현재의 위치를 기반으로 검색을 합니다.
예를 들어서 module5.py에서 module4의 class4라는 클래스를 사용하려면 다음과 같이 사용합니다.

from ..module4 import class4

..은 현재위치에서 상위 디렉토리로 가는 경로를 뜻합니다.

3. main module 에서 패키지의 모듈을 어떻게 import 해야할까요?

3.1) calculator 패키지 만들기

  • 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)

3.2) main.py에서 상대경로로 add_and_mutiply 를 import 했을 때 발생하는 에러는?

다음과 같이 상대경로로 알수없는 부모 패지키를 import하려 했다고 에러가 뜹니다.
ImportError: attempted relative import with no known parent package

3.3) main module 에서는 패키지의 모듈을 어떻게 import 해야하나

- 참고자료 -

- 정답: 절대경로를 사용해서 import 한다.
: 절대경로를 사용해서 import하니 출력값이 5가 나왔고 에러문구가 뜨지 않았습니다.

- 상대경로로 import할 경우 에러문구가 뜨는 이유

Note that relative imports are based on the name of the current module. Since the name of the main module is always "main", modules intended for use as the main module of a Python application must always use absolute imports.

상대경로는 현재 모듈을 기준으로 모듈/패키지를 찾기 때문에, 이름이 main 모듈이면 항상 메인이라서 반드시 절대 경로를 사용해야 한다고 합니다.

3.4) add_and_multiply.py에서 multiply함수를 절대경로와 상대경로로 각각 import 해보고 main 모듈과 차이점을 생각해보고 결과를 출력해 보기

  • multiply함수를 절대 경로 로 import할 경우,
    절대경로: from calculator.multiplication import multiply
    다음과 같은 오류가 뜬다.
    ModuleNotFoundError: No module named 'calculator'

current directory 라고 하는 현재의 프로젝트 디렉토리는 default로 sys.path 에 포함되게 됩니다.
그러므로 절대경로는 current directory 로 부터 경로를 시작해야 합니다.

  • multiply함수를 상대 경로 로 import할 경우,
    상대경로: from .multiplication import multiply
    다음과 같은 오류가 뜬다.
    ImportError: attempted relative import with no known parent package

add_and_multiply.py와 multiplication.py는 같은 디렉토리에 있기 때문에
상대 경로 from .multiplication import multiply 대신에
from multiplication import multiply을 사용하면 오류가 안뜬다.

4. __init__.py 파일의 역할은?

__init__.py 파일은 __init__.py 파일이 있는 디렉터리가 패키지이며, 해당 디렉토리의 파일들이 패키지에 포함 되어 있음을 알려주는 역할을 합니다.
또한 __init__.py 파일을 사용하여 사용하고자 하는 함수의 경로를 줄여줄수 있습니다.

참고로 __init__.py파일안에 __all__ 변수를 써서 사용되는 숨기고 싶은 함수를 숨길 수 있습니다.
__all__의 기본값은 모든 함수,변수,클래스인데, 감추고 싶은 함수,변수,클래스는 빼고
보여줄 함수,변수,클래스만 적으면 감춘 함수,변수,클래스는 import로 불러와서 사용할 수 없습니다.

적용하는 방법은
__init__.py 파일안에 __all__를 사용하여 문자열로 import 되길 원하는 요소들을 리스트안에 넣어 사용합니다.
예)

# __init__.py
from .mod1 import func2
from .mod2 import func3

__all__ = ['func2', 'func3']
  • python3.3 버전부터 __init__.py 파일이 없어도 패키지로 인식하기 때문에 안써도 되지만 python3.3 이전 버전에서는 __init__.py 파일을 생성해서 사용해야 합니다.
profile
함께 성장하는 개발자가 되고 싶습니다.

0개의 댓글