TIL51 . 파이썬이 모듈과 패키지를 검색하는 법

Jaeyeon·2021년 3월 19일
0
post-thumbnail

✅ import search 순서

import abc

abc라는 모듈 or 패키지를 파이썬에서는 어떻게 가져 오는 걸까??

  1. sys.modules
  2. built-in modules
  3. sys.path

이 세가지 장소를 순서대로 보면서 찾아 보겠다.

1. sys.modules

  • 파이썬이 모듈이나 패키지를 찾기 위해 가장 먼저 확인하는 곳이다.
  • 단순한 딕셔너리로 구성 되어있고 이미 import된 모듈과 패키지들을 저장하는 저장소 역할이다.
  • 그러므로 새로 import 하는 모듈은 sys.modules에서 찾을 수 없다.

2. built-in modules

  • 파이썬에서 제공하는 공식 라이브러리 이다.
  • built-in module들은 파이썬에 포함 되므로 쉽게 찾을 수 있다.

3. sys.path

  • 기본적으로 list이며 string을 감싸고 있는 list이다.
    ['',
     '/Users/song-eun-u/anaconda3/bin',
     '/Users/song-eun-u/anaconda3/lib/python36.zip',
     '/Users/song-eun-u/anaconda3/lib/python3.6',
     '/Users/song-eun-u/anaconda3/lib/python3.6/lib-dynload',
     '/Users/song-eun-u/anaconda3/lib/python3.6/site-packages',
     '/Users/song-eun-u/anaconda3/lib/python3.6/site-packages/aeosa',
     '/Users/song-eun-u/anaconda3/lib/python3.6/site-packages/IPython/extensions',
     '/Users/song-eun-u/.ipython']

    sys.path를 뜯어보면 이렇게 경로가 표시 되어있는데 import하고자 하는 패키지가 여기 있는지 확인한다.

4. Error

  • 위의 3가지 방법으로도 찾지 못한다면
    ModuleNotFoundError 에러를 리턴하게 된다.


✅ Absolute Path & Relative Path

  • 모듈과 패키지는 위의 세가지의 경우에서는 문제없이 잘 찾아진다.

  • 하지만 직접 개발한 local package는 import할 때 해당 패키지의 위치에 맞게 import경로를 잘 선언 해야 한다.

    로컬 패키지를 import 하는 경로에는 두가지 방법이 있다.

    1. absolute path

    2. relative path

absolute path (절대 경로)

  • import를 하는 파일이나 경로에 상관없이 항상 경로가 동일 하기 때문에 절대 경로이다.

아래 my_app이라는 프로젝트를 예로 들어보겠다.

여기서 main.py에 패키지를 import 해오는 것은 아래의 이미지와 같이 import 할 수 있다.

예를 들어 package2안에 subpackage1안에 module5 안에 function2라는 함수를 사용 하고 싶다 할때는

from package2.subpackage1.module5 import function2

위와 같이 import해 올 수 있다.

  • my_app 프로젝트 내에서는 어느 파일, 어느 위치에서 import 하던지 경로가 항상 위와 같이 동일하게 되므로 absolute path 라고 하는 것입니다.

relative path (상대 경로)

  • absolute path를 사용하게 되면 경로가 길어질 수 있다는 단점을 보완하기 위해 상대경로를 사용한다.
  • absolute path와 다르게 최상단 디렉토리 기준이 아니고 import하는 위치를 기준으로 경로를 정의한다.
  • 일반적으로 로컬패키지 -> 다른 로컬 패키지로 import 할 때 사용된다.

예를 들어, package2의 module3에서 package2의 class1과 package2의 하위 package인 subpackage1의 module5의 function2 함수를 import 하려고 하면 다음 처럼 할 수 있습니다.

# package2/module3.py
from . import class1
from .subpackage1.module5 import function2

여기서 .은 import가 선언되는 파일의 현재 위치를 이야기 한다.
현재 위치는 package2/module3.py이므로 현재 위치에서부터 원하는 모듈의 경로만 선언해주면 되는 것이다.

..은 현재위치에서 상위 디렉토리로 가는 경로이다.

# subpackage1/module5.py
from ..module4 import class4
  • 경로의 길이를 줄여준다는 장점이 있지만 파일위치가 변경 되면 경로 위치도 변경되어야 하는 단점이 있어 웬만해서는 absolute path를 사용한다.

1. sys.modules 와 sys.path의 차이점을 서술해 주세요.

  • sys.modules는 패키지나 모듈을 찾을 때 파이썬이 제일 먼저 실행하는 방법으로써 전에 import가 되었던 패키지와 모듈을 탐색하는 것 입니다. 또한 타입이 딕셔너리이다.
    sys.path는 파이썬에서 마지막으로 패키지나 모듈을 찾을 때 사용하는 방법으로써 import하고자 하는 패키지나 모듈을 경로를 통해서 확인한다. 타입은 리스트이다.

2. sys 도 import 해야하는 모듈입니다. 파이썬은 sys 모듈의 위치를 어떻게 찾을 수 있을까요?

  • sys는 기본적으로 파이썬에서 포함되는 모듈로서 built-in modules에서 찾거나 만약 못찾는 다면 sys.path에서 쉽게 찾을 수 있다.

3. Absolute path와 relative path의 차이점을 서술해 주세요.

  • 절대 경로는 최상위 디렉토리부터 찾아가는 방식이며 상대경로는 현재 파일 기준으로 import 해올 모듈의 경로를 찾아 가는 차이점이 있습니다.

4. calculator 패키지 만들기

__init__.py

파일에는 아무코드도 없지만 init 파일은 해당 디렉토리가 패키지임을 알려주는 역할을 합니다.

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 .multiply import multiply
#from calculator.multiply import multiply
def add_and_multiply(a,b):
    return multiply(a,b) + (a+b)

multiplication.py

def multiply(a,b):
    return(a*b)

5. main.py에서 상대경로로 add_and_mutiply 를 임포트 했을 때 발생하는 에러를 확인하고, 다음의 파이썬 공식 문서를 참고해서 main module 에서는 패키지의 모듈을 어떻게 임포트 해야하는지 블로깅 해주세요.
https://docs.python.org/3/tutorial/modules.html#intra-package-references

이 오류는 main.py 파일이 최상위 파일이라는 것을 알려준다.
상대경로를 주석처리하고 절대경로로 import하면 다음과 같이 결과가 잘 출력된다.

6. add_and_multiply.py에서 multiply함수를 절대경로와 상대경로도 각각 임포트 해보고 main 모듈과 차이점을 생각해보고 결과를 출력해 보세요.

절대경로로 실행을 했을 때는 문제없이 컴파일이 되지만
상대경로로 실행을 했을 때는 다른 모듈로 Import를 해온 후 __main__으로 실행을 시키기 때문에 파이썬에서 해당파일의 위치를 정확히 알기가 쉽지 않다.
하지만 add_and_multiply를 직접 컴파일 하지 않고 다른 곳에서 import로 add_and_multiply를 불러오면 정상적으로 실행이 가능하다.

7.__init__.py 파일의 역할에 대해서도 정리해서 블로깅 해주세요.

  • init 파일은 해당 디렉토리가 패키지임을 알려주는 역할을 합니다.
  • package가 import 될 때 초기 설정 목적으로 __init__.py를 사용한다.
  • package 안에 __init__.py 가 있으면 패키지가 임포트 될 때 __init__.py파일의 코드들이 자동으로 실행 된다.
profile
생각하는 개발자 되기

0개의 댓글