- 모듈 / 패키지 import하기
- Absolute Path / Relative Path
- sys.module과 sys.path의 차이점
파이썬에서는 import.모듈
또는 from 모듈 import 이름
로 모듈을 가져올 수 있다.
import my_import
위와 같은 코드를 추가 했을 때 파이썬은 sys.modules
- built-in modules
- sys.path
순으로 모듈/패키지를 찾는다.
sys.modules
sys는 파이썬에 포함되어있는 모듈이며, sys.modules은 이미 import된 모듈 및 패키지를 저장하는 디렉터리이다. 따라서 새로이 import되는 것들은 이곳에서 찾을 수 없다.
built-in modules
파이썬에서 제공하는 공식 라이브러리이며, 찾는 모듈/패키지가 sys.modules에 없을 때 그 다음으로 찾아보는 곳이다.
sys.path
sys.path는 아래와 같이 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']
리스트에 저장되어 있는 리스트를 확인하면서 찾고자하는 모듈/패키지가 있는지 검색한다.
pip으로 외부 모듈을 설치 시 자동으로 site-pakages에 설치되는데 site-pakages 역시 sys.path에 포함되어 있어 pip으로 설치한 모듈/패키지도 여기서 찾을 수 있다.
여기까지 검색을 했는데도 찾을 수 없는 경우 ModuleNotFoundError
를 일으킨다.
직접 작성한 local pakage의 경우 경로가 파이썬이 모듈/패키지를 잘 찾을 수 있도록 경로를 잘 명시해주는 것이 중요하다.
경로가 최상단 디렉터리부터 시작하며 같은 프로젝트 내의 어떤 파일, 경로나 상관없이 항상 동일한 경로이다.
└── my_app
├── main.py
├── package1
│ ├── module1.py
│ └── module2.py
└── package2
├── __init__.py
├── module3.py
├── module4.py
└── subpackage1
└── module5.py
위와 같은 구조를 가진 프로젝트가 있다고 하자. module5.py와 module1.py내의 func1을 import한다고 하면 다음과 같이 경로를 지정한다.
from pakage2.subpakage2 import module5.py
from pakage1.module2.py import func1
absolute path의 단점은 경로가 길어질 수 있다는 점이다.
반면 Relative Path는 현재 import를 하는 위치를 기준으로 경로를 정의한다. 따라서 Relative Path는 Local Pakage 내에서 다른 Local Pakage를 import할 때 사용한다.
예를 들어, pakage2의 module4.py에서 module1.py와 module5.py, moulde4.py에 있는 class1을 import한다면 다음과 같이 경로가 지정될 것이다.
from . import class1
from .subpakage1 import module5.py
from ..module4 import class4
.(dot)은 현재 위치를 나타내고 상위 디렉터리로 가고 싶으면 ..을 쓴다. 상대 경로는 경로를 단축화할 수 있으나 파일의 경로가 달라질 경우 import 경로도 모두 수정을 해줘야하기 때문에 절대 경로를 더 권장한다.
main.py 에서 상대 경로로 다른 메서드를 import한다면 다음과 같은 에러를 볼 수 있다.
ImportError: attempted relative import with no known parent package
앞서 상대 경로는 자신의 위치를 잡기 위해 __name자신의 현재 모듈 이름을 기반으로 위치를 잡는 것인데, main 모듈은 항상 '__main' 이기 때문에 main 모듈에서는 절대 경로로 지정해줘야 한다.
├── main.py
├── calculator
├── __init__.py
├── add_and_multiply.py
└── multiplication.py
위와 같은 구조를 가진 패키지가 있다고 할 때, add_and_multiply.py에서 multiplication.py 내의 multiply 함수를 import 한다고 하자.
다음과 같이 작성할 수 있을 것이다.
from calculator.multiplication.py import multiply # 절대 경로
from .multiplication.py import multiply # 상대 경로
이때 상대 경로로 작성하면 오류가 나는데, main.py에서 처럼 main module인 add_and_multiply.py를 찾지 못해서 나오는 오류이다.
__init.py__는 해당 디렉터리가 패키지임을 보여준다. (python3.3 부터는 없어도 패키지로 인식하지만 하위 버전을 고려하여 생성하는 것이 나음)
import하면 이 파일이 실행되며 초기화를 하기도 한다. 예를 들어 패키지 내의 모든 모듈들이 공통으로 사용하는 외부 모듈 / 패키지가 있다면 이 파일에 import하여 패키지 전체에서 쓸 수 있도록 한다.
참고:
Calculator 패키지 만들기
[파이썬 상대경로 import 에러] ImportError: attempted relative import with no known parent package