TIL — Modules & Packages

이성보·2020년 10월 26일
0

python

목록 보기
3/7
post-thumbnail

Import Search 순서

파이썬은 모듈/package 를 찾을 때 아래와 같은 순서로 찾습니다.

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

sys.modules 은 파이썬이 모듈이나 package를 찾기위해 가장 먼저 확인하는 곳입니다.

sys.modules는 단순한 dictionary 입니다. 그리고 이미 import된 모듈과 package들을 저장하고 있습니다.
즉, 한번 import된 모듈과 package들은 파이썬이 또 다시 찾지 않아도 되도록 하는 기능을 가지고 있습니다.
그러므로 새로 import 하는 모듈은 sys.modules 에서 찾을 수 없습니다.

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

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 하고자 하는 package가 위치해 있는지 확인합니다.

정리를 하자면, 파이썬은 import 하고자 하는 모듈과 package를 찾을때에 먼저 sys.modules를 보고, 없으면 파이썬 built-in 모듈들을 확인 하고 마지막으로 sys.path에 지정되어 있는 경로들을 확인해서 찾습니다.
sys.path 에서도 못찾으면 ModuleNotFoundError 에러를 리턴합니다.


sys도 import 해야하는 모듈인데 파이썬은 sys 모듈의 위치를 어떻게 찾을 수 있을까요?

import sys
...
print(sys)
----출력결과----
<module 'sys' (built-in)>
sys를 import 한뒤에 출력해 보면 built-in modules 이라는 것을 알 수 있습니다. 그렇기 때문에 별도의 설치없이 바로 사용할 수 있습니다.


Absolute Path & Relative Path

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

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

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

일반적으로 local package를 import 할때는 absolute path를 사용하면 됩니다.
다만 absolute path를 사용하게 되면 한가지 단점이 있는데 바로 경로가 길어질 수 있다는 점입니다.
그래서 이러한 단점을 보완하기 위해서 relative path를 사용할 수 있습니다.

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


relative imports 는 현재 모듈의 이름을 기반으로 합니다.
메인 모듈의 이름은 항상 "main" 이기 때문에 메인 모듈로 사용하려는 모듈은 항상 absolute imports 를 사용해야 합니다.


Relative path는 선언해야 하는 경로의 길이를 줄여준다는 장점은 있지만 헷갈리기 쉽고 파일 위치가 변경되면 경로 위치도 변경되어야 하는 단점이 있습니다. 그러므로 웬만한 경우 absolute path를 사용하는게 권장 됩니다.

init_.py 파일의 역할

Package 안에 init.py 파일이 있으면 package가 import 될때 init.py 파일의 코드들이 자동으로 실행됩니다. 그렇다면 init.py 파일을 통하여 정확히 무엇을 할 수 있는걸까요?
일반적으로 다음 사항들을 할 수 있습니다.

Import 할때 경로의 총 길이 줄여주기

import pkg.mod1

pkg.mod1.func2()

func2 함수를 호출 할때마다 매번 모든 경로를 다 타입해줘야 하기때문에 번거롭습니다.
함수 이름을 곧바로 호출 할 수 있게 하면 편할것 같습니다. 다행히도 init.py 파일을 통해 함수의 경로를 줄여줄 수 있습니다. 방법은 아주 간단합니다. init.py 파일에 먼저 한번 import 해주면됩니다.

# __init__.py
from .mod1 import func2
# main.py
from pkg import func2

func2()

Package에서 import 할 수 있는 변수/함수/클래스 제한하기

init.py 파일을 사용해서 import 할 수 있는 변수/함수/클래스를 제한할 수 있습니다.
예를 들어 모듈의 모든 함수가 다 외부로 노출될 수 있는건 아닐수 있습니다. 내부적으로만 사용되어야 하는 함수도 있을수 있는데요, 이러한 함수가 package 외부에서 import되어 사용되는 것을 막기 위해서는 all 변수를 지정해 줄 수 있습니다.

package를 통해 import 될 수 있는 요소들은 모두 all 변수를 통해 정의 됩니다.
그리고 all 변수의 default 값은 모든 함수/변수/클래스 입니다.
그러므로 all 변수를 따로 정의해줌으로 import 될 수 있는 요소들을 제한할 수 있는 것입니다.
all 변수는 string 값의 요소를 가지고 있는 list 입니다 (list of strings).
그러므로 import 되길 원하는 요소들을 string으로 list에 선언해주면 됩니다.

그 외 package가 import될때 꼭 먼저 실행되어야 하는 코드들

0개의 댓글