파이썬은 다음 3가지 장소를 순서대로 보면서 찾는다.
sys.modules
built-in modules
sys.path
파이썬이 모듈이나 package를 찾기위해 가장 먼저 확인하는 곳이다.
sys.modules는 단순한 dictionary 이며, 이미 import된 모듈과 package들을 저장하고 있다.
즉, 한번 import된 모듈과 package들은 파이썬이 또 다시 찾지 않아도 되도록 하는 기능을 가지고 있다.
그러므로 새로 import 하는 모듈은 sys.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가 위치해 있는지 확인한다.
참고로 sys 는 파이썬에 포함되어 있는 모듈이다. 그러므로 다음 처럼 sys 모듈을 import 해서 sys.modules와 sys.path 를 출력할 수도 있고 수정할 수도 있다.
import sys
print(sys.path)
print(sys.modules)
정리를 하자면, 파이썬은 import 하고자 하는 모듈과 package를 찾을때에 먼저 sys.modules를 보고, 없으면 파이썬 built-in 모듈들을 확인 하고 마지막으로 sys.path에 지정되어 있는 경로들을 확인해서 찾는다.
sys.path 에서도 못찾으면 ModuleNotFoundError 에러를 리턴
sys.modules과 sys.path를 각각 출력해봤다.
sys.modules는 Dict 형태로 module/package가 key로, module/package의 경로가 value로 출력된다.
sys.path는 List형태로 module/package가 설치된 Directory가 출력된다.
sys 모듈은 파이썬 인터프리터가 제공하는 변수와 함수를 직접 제어할 수 있게 해주는 모듈이다.
인터프리터(interpreter)란 소스 코드를 처음부터 한 라인씩 차례대로 해석하며 실행하는 프로그램입니다.
sys를 출력해보니 built-in 이라 뜬다.
파이썬이 두번째로 찾는 built-in modules 에서 찾은 것
파이썬의 built-in 모듈과 pip 을 통해 설치한 외부 모듈 및 package는 일반적으로 import 하는데 큰 문제가 되지 않는다.
Built-in 모듈은 당연히 잘 찾아지고, pip 으로 설치한 외부 모듈도 자동으로 site-packages
라는 디렉토리에 설치가 되는데, 이 site-packages
는 sys.path
에 이미 포함되어 있기때문에 찾는데 문제가 없다.
문제는 직접 개발한 local package를 import 할때는 해당 package의 위치에 맞게 "import 경로"를 잘 선언해야 한다.
다음과 같은 프로젝트로 예를 들어보자면
└── my_app
├── main.py
├── package1
│ ├── module1.py
│ └── module2.py
└── package2
├── __init__.py
├── module3.py
├── module4.py
└── subpackage1
└── module5.py
절대경로 ex)
subpackage1
의 module5
모듈의 function2
함수를 import 하려면?
from package2.subpackage1.module5 import function2
# 이미 my_app 프로젝트 안에 있으므로 my_app 은 생략
상대경로 ex)
module3
에서 package2
의class1
, module1
의 function2
함수를 import 하려면?
# module3.py
from . import class1
from ..package1.module1 import function2
# .은 파일의 현재 위치
# ..은 현재위치에서 상위 디렉토리로 이동
Relative path(상대경로)는 선언해야 하는 경로의 길이를 줄여준다는 장점은 있지만 헷갈리기 쉽고 파일 위치가 변경되면 경로 위치도 변경되어야 하는 단점이 있다.
그러므로 웬만한 경우 absolute path(절대경로) 사용을 권장
라이브러리는 필요한 코드를 재사용하기 위해 언제든지 필요한 곳에서 호출할 수 있도록 개발자들에 의해서 이미 만들어진 클래스나 함수를 모아놓은 것을 말한다.