20/03/31 TIL

Magit·2020년 3월 31일
0

TIL

목록 보기
6/16

How import statement finds modules and packages

  • 파이썬은 module과 package를 어떻게 찾을까?
  • 그 과정에 대해 알아보자.

import search 순서

  • abc라는 package가 있다고 가정해보자. 그리고 abc 패키지를 사용하려면 다음처럼 import 해야한다.
  • import abc
  • 단순한 파이썬 파일(모듈일 경우) 이거나 파이썬 파일들을 담고 있는 디렉토리(package인 경우)이다. 그러므로 해당 파일이나 디렉토리가 어디있는지 파이썬이 찾을 수 있어야 import가 가능하다.
  • 파이썬은 다음 3가지 장소를 순서대로 보면서 찾는다.
    • sys.modules
    • built-in modules
    • sys.path

sys.modules

  • 파이썬이 모듈이나 패키지를 찾기 위해 가장 먼저 확인하는 곳
  • sys.modules는 단순한 dictionary이다. 그리고 이미 import된 모듈과 package들을 저장하고 있다. 즉, 한 번 import 된 모듈과 패키지들은 파이썬이 또 다시 찾지않아도 되도록 하는 기능을 갖고 있다. 그러므로 새로 import 하는 모듈은 sys.modules에서 찾을 수 없다.

built-in modules

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

sys.path

  • 마지막으로 보는 장소가 바로 sys.path이다.
  • 기본적으로 list이며 string 요소들을 가지고 있는 list이다.
  • 각 string 요소들은 다음 처럼 경로를 나타낸다.
['',
 '/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']
  • 그러므로 파이썬은 list의 각 경로를 하나하나 확인하면서 해당 경로에 import 하고자 하는 패키지가 위치해있는지 확인한다.

  • 참고로 sys는 파이썬에 포함되어 있는 모듈이다. 그러므로 다음 처럼 sys 모듈을 import 해서 sys.modules 와 sys.path를 출력할수도 있고 수정할 수도 있다.

    import sys
    print(sys.path)
    print(sys.modules)
  • 정리하자면, 파이썬은 import 하고자 하는 모듈과 패지키를 찾을 때에 먼저 sys.modules를 보고, 없으면 파이썬 built-in 모듈들을 확인하고 마지막으로 sys.path에 지정되어 있는 경로들을 확인해서 찾는다.

  • sys.path에서도 못찾으면 ModuleNotFoundError 에러를 리턴한다.

    absolute path & relative path

  • 파이선의 built-in 모듈과 pip 을 통해 설치한 외부 모듈 및 패키지는 일반적으로 import하는데 큰 문제가 되지 않는다. 빌트인 모듈은 당연히 잘 찾아지고 pip으로 설치한 외부 모듈도 자동으로 site-packages 라는 디렉토리에 설치가 되는데, 이 site-packages는 sys.path에 이미 포함되어 있기때문에 찾는데 문제 없다.

  • 문제는 직접 개발한 local package인데, 직접 개발한 local package 를 import 할때는 해당 package의 위치에 맞게 import 경로를 잘 선언해야 한다. local package를 import 하는 경로에는 absolute path와 relative path가 있다.

  • Absolute path는 이름 그대로 절대 경로인데, 왜 절대 경로이냐면 import를 하는 파일이나 경로에 상관없이 항상 경로가 동일하기 때문이다.

└── my_app
    ├── main.py
    ├── package1
    │   ├── module1.py
    │   └── module2.py
    └── package2
        ├── __init__.py
        ├── module3.py
        ├── module4.py
        └── subpackage1
            └── module5.py
  • my.app 이라는 프로젝트이며 package1 과 package2 라는 2개의 패키지를 가지고 있다. 그리고 package2는 subpackage2 라는 중첩 중첩 패키지를 가지고 있다.
  • Absolute path를 사용해 package1과 package2를 import 하면 다음과 같다.
from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1.module5 import function2
  • 경로들의 시작점이 전부 "my_app" 프로젝트의 가장 최상위 디렉토리에서 시작하는 것을 볼 수 있다.
  • 예를 들어, subpackage1의 module5 모듈의 function2 함수를 import 하기 위해서는 다음 경로를 거치게 된다.
my_app => package2 => sybpackage1 => module5.py
  • 이걸 리눅스의 directory 경로 형식으로 바꾸면 다음처럼 표현 할 수 있다.
my_app/package2/subpackage1/module5.py
  • 윈도우스 형식이라면 다음과 같다.
my_app\packaage2\subpackage1\module5.py
  • 파이썬에서는 slash(/) 나 back slash() 대신에 dot(.)을 사용해서 경로를 표현한다.
my_app.package2.subpackage1.module5.py
  • 이미 my_app 프로젝트 안에 있으므로 my_app은 생략되고 다음처럼 표현하게 된다.
package2.subpackage1.module5.py
  • 이걸 from import 키워드를 사용해서 import 하게 되면 다음 처럼 되는 것이다.
from package2.subpackage1.module5 import function2
  • my_app 프로젝트 내에서는 어느 파일, 어느 위치에서 import 하던지 경로가 항상 위와 같이 동일하게 되므로 absolute path라고 하는 것이다.

  • 참고로 current directory 라고 하는 현재의 프로젝트 디렉토리는 default로 sys.path 에 포함된게 된다. 그러므로 absolute path는 current directory 로 부터 경로를 시작하게 되는것이다.

  • 일반적으로 local package를 import 할때는 absolute path 를 사용하면 된다. 다만 절대경로를 사용하게 되면 한가지 단점이 있는데, 경로가 길어질 수 있다는 점이다.

  • 그런 단점을 보완하기 위해 relative path를 사용할 수 있다.

  • relative path는 absolute path와 다르게 프로젝트의 최상단 디렉토리를 기준으로 경로를 잡는게 아니라 import하는 위치를 기준으로 경로를 정의한다. relative path는 local package 안에서 다른 local package를 import 할때 사용된다.

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

# package2/module3.py

from . import class1
from .subpackage1.module5 import function2
  • 여기서 dot(.)은 import가 선언되는 파일의 현재 위치를 이야기 한다. 현재위치는 package2/module3.py 이므로 현재 위치에서부터 원하는 모듈의 경로만 선언해주면 되는 것이다.
  • 또한 dot 2개를 사용할 수도 있다. dot 2개(..)는 현재위치에서 상위 디렉토리로 가는 경로이다.
# subpackage1/module5.py
from ..module4 import class4
  • relative path 는 선언해야 하는 경로의 길이를 줄여준다는 장점은 있지만, 헷갈리기 쉽고 파일 위치가 변경되면 경로 위치도 변경되어야 하는 단점이 있다. 웬만하면 absolute path를 사용하는게 권장된다.




Assignment

이번 과제는 코딩 과제가 아니라 서술형 과제입니다. 다음 문제들을 읽으시고 답을 블로깅 한후 슬랙 채널에 공유해주세요.

  1. sys.modules 와 sys.path의 차이점을 서술해 주세요.
  2. sys 도 import 해야하는 모듈입니다. 파이썬은 sys 모듈의 위치를 어떻게 찾을 수 있을까요?
  3. Absolute path와 relative path의 차이점을 서술해 주세요.

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

  • sys.modules

    • 파이썬이 제일 먼저 모듈이나 패키지를 찾는 장소
    • 딕셔너리 구조
    • 한 번이라도 import 되있는 모듈과 패키지가 저장되있음 (다시 찾을 필요 없음)
    • 한 번 이상 사용되었거나 이미 내장된 모듈이나 패키지만 존재하므로 새롭게 import 된 것들은 없다.

    import sys
    print(sys.modules)
    로 현재 내 pc의 모듈들을 볼 수 있다.
    모듈이름:모듈객체 형태의 딕셔너리 구조인것을 확인할 수 있다.
  • sys.path

    • 모듈과 패키지를 찾을 때 마지막에 sys.path를 찾게된다.

    • 리스트 구조(string 요소)

    • 리스트 요소의 처음부터 마지막까지 찾는다.

    • 모듈과 패키지의 검색 위치를 제공하는 단순한 절대경로들의 리스트이다.

    • sys.path에서도 모듈을 찾지 못하면 ModuleNotFoundError 에러를 리턴한다.

     import sys
     print(sys.path)
     로 sys.path를 출력해보면 list 형태로 되있는것을 확인해볼수 있다.
     
     기본적인 순서는
     1. 현재 디렉토리
     'Users/magrfs/Desktop/Wecode'
     
     2. 환경변수 PYTHONPATH에 지정된 경로
     3. python이 설치된 경로 및 그 밑 라이브러리 경로
     '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
     '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7'
    ...
    ...
    

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

  • 맨 처음에는 sys 모듈이 import 되었던적이 있는지 확인할것이다.
  • 그러나 import 된 적이 없었다면 결국 모듈을 찾아다니다가 built-in modules로 넘어가서 sys 모듈을 찾고서 import 할 것이다. 위에서 코드를 찾아보면 'sys': <module 'sys' (built-in)> 으로 built-in 되있다.

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

  • Absolute path (절대경로)
    • Absolute path (절대경로)는 최상위 디렉토리부터 모듈 및 패키지까지 생략, 축약되지 않고 명확히 명시된 경로이다.
    • 어디에서 써도 항상 같아서 헷갈리지 않지만, 구조등을 변경하기 어려운, 즉, 유연성이 부족하다는 단점이 있고 경로가 길어질 수 있다는 단점이 있다.
      예를 들어 위에 첨부된 사진중 path 부분 사진이 내 컴퓨터에 저장된 경로는
      /Users/magrfs/Desktop/Velog/sys_path.png
      이다.
      이렇게 시작부터 끝까지 경로를 적는걸 절대경로라고 할 수 있다.
  • Relative path (상대경로)
    • 현재 작업중인 디렉토리를 기점으로 찾아갈 파일의 디렉토리를 표시한 것이다.
    • 현재 디렉토리를 . 으로 표시하고 현재 디렉토리의 상위 디렉토리를 .. 으로 표시한다.
    현재 Velog 디렉토리에 있다면
    ./sys_path.png
    라고 표현할 수 있고
    ../Velog/sys_path.png
    라고 표현할 수도 있다.
    • 절대경로에 비해서 간결해지는 장점은 있지만 프로젝트가 커질수록 복잡도가 높아져서 혼동되기 쉽고, 파일 위치가 변하면 path도 재설정해줘야한다.
profile
이제 막 배우기 시작한 개발자입니다.

0개의 댓글