1. sys.modules
2. built-in modules
3. sys.path
-> 파이썬은 위와 같은 순서로 모듈/package를 찾음
-> 모듈이나 package
를 찾기 위해 가장 먼저 확인하는 곳
-> 단순한 dict
이고, 이미 import
된 모듈과 package
들을 저장하고 있음(재탐색 방지 기능)
-> 새로 import
하는 모듈은 sys.modules
에서 찾을 수 없음
-> 파이썬 공식 라이브러리들
-> 해당 모듈들은 이미 파이썬에 포함되어 나오므로 파이썬이 쉽게 찾을 수 있음
-> 가장 마지막으로 보는 장소. list
이며, str
요소들을 가지고 있음
-> 각 str
요소들은 다음처럼 경로를 나타냄.
-> 각 경로를 one by one 확인하면서 해당 경로에 import
하고자 하는 packages
가 위치해 있는지 확인함
['',
'/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
는 파이썬에 포함된 모듈. 아래와 같이 sys
모듈을 import
해서 sys.modules
과 sys.path
를 출력, 수정 할 수도 있음
import sys print(sys.path) print(sys.modules)
-> In other words, 파이썬은 import
하고자 하는 모듈과 package
를 찾을 때,
[sys.modules
확인 -(no)> python built-in 모듈
확인 -(no)> sys.path
지정 경로로 확인]
-> sys.path
에서도 못 찾으면 ModuleNotFoundError
를 리턴함
-> Local package
를 import
하는 경로에는 absolute path
, relative path
가 있음
absolute path
: 절대 경로. import
하는 파일이나 경로에 상관없이 항상 경로가 동일└── my_app ├── main.py ├── package1 │ ├── module1.py │ └── module2.py -- function1 └── package2 ├── __init__.py -- class1 ├── module3.py ├── module4.py -- class4 └── subpackage1 └── module5.py -- function2 from package1 import module1 from package1.module2 import function1 from package2 import class1 from package2.subpackage1.module5 import function2 [linux] my_app/package2/subpackage1/module5.py [window] my_app\package2\subpackage1\module5.py [python] (my_app.)package2.subpackage1.module5.py -> 실제로는 my_app이 생략됨
-> 하지만 경로가 길어질 수 있다는 단점이 존재[relative path
]를 사용하는 이유
-> 프로젝트 최상단 디렉토리가 아닌 import
하는 위치를 기준으로 경로를 정의
-> 일반적으로 relative path
는 local package
안에서 다른 local package
를 import
할 때 사용 됨
ex> package2의 module3에서 package2의 class1과 package2의 하위인 subpackage1 의 module5의 function2함수를 import 하라 # package2/module3.py from . import class1 from .subpackage1.module5 import function2 "(.) 은 import가 선언되는 파일의 현재 위치" "(..) 은 현재 위치에서 상위 디렉토리로 가는 경로" # subpackage1/module5.py from ..module4 import class4
-> relative path
는 선언해야 하는 경로의길이를 줄여준다는 장점. but,
-> 헷갈리기 쉽고 파일 위치가 변경되면 경로 위치도 변경되어야 하는 단점이 존재
-> 그러므로 웬만한 경우 absolute path
를 사용하는 것을 권장
sys.modules
와 sys.path
의 차이점(1) 파이썬이 모듈/package를 찾을 때 sys.modules가 첫번째, sys.path를 마지막으로 찾는다.
(2) sys.modules는 dict, sys.path는 list의 형태를 갖는다.
sys
도 import
해야하는 모듈인데, 파이썬은 sys
모듈의 위치를 어떻게 찾을 수 있을까?(1) 'sys`는 파이썬에 포함된 모듈이다.
Absolute path
와 relative path
의 차이점(1) `Absolute path`
- import하는 파일이나 경로에 상관없이 항상 경로가 동일
- 프로젝트 최상단 디렉토리가 아닌 import하는 위치를 기준으로 경로를 정의
(2) `Relative path`
- 선언해야 하는 경로의길이를 줄여준다는 장점
- 헷갈리기 쉽고 파일 위치가 변경되면 경로 위치도 변경되어야 하는 단점
"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 .multiplication import multiply from calculator.multiplication import multiply def add_and_multiply(a,b): return multiply(a,b) + (a+b) "multiplication.py" def multiply(a,b): return(a*b)
main.py
에서 상대경로로 add_and_multiply
를 임포트 했을 때 발생하는 에러를 확인하고,module에서는 패키지의 모듈을 어떻게 임포트 해야하는지?(1) 메인이 되는 모듈의 이름은 항상 "__main__" 이기 때문에, 메일 모듈로 사용될 목적의 모듈들은
반!드!시! "절대 임포트"를 사용해야 한다. --파이썬 공식 문서에서 발췌
add_and_multiply.py
에서 multiply
함수를 절대경로와 상대경로로 각각 임포트 해보고 main모듈과의 차이점 서술(결과 포함)(1) relative path
- 해당 파이썬 모듈 구동 시, 자동으로 main 모듈로써 인식을 하면서
모듈의 name이 바뀌기 때문에 경로를 찾지 못함.
(2) absolute path
- 상대 경로일때와 같은 에러 메세지가 아니라서 그 이유를 찾아 헤맸지만, 정확한 이유는 찾지 못함.
메세지의 내용과 그나마 모은 정보를 취합해보자면, calculator 하위 디렉토리에서
또 다시 calculator 라는 모듈을 찾으려고 하는 것 같아 보임.
당연히 그런 모듈은 없으므로 에러 발생.
-> 과제를 이해하기에 따라서 과제 수행 방식이 두 가지로 갈라지는데,
(1) add_and_multiply.py
내부에서 Run 했을 때 상대 & 절대경로 간의 차이점
(2) add_and_multiply.py
에서 경로를 상대 or 절대로 바꾼 다음, main.py
로 이동해서 Run 했을 때 어떤 반응이 있는지 확인하기
-> 필자가 수행한 방법은 (1)이고, (2) 방식대로 수행했을 때의 결과는 두 경로 모두 잘 실행되었음.
--> 요점은 main
이 되는 모듈을 구동할 때 해당 모듈의 name
이 __main__
으로 변경되기 때문에,
relative path
는 main
이 되는 모듈에서 사용할 수 없다는 것,
그 외 다른 모듈에서는 relative
든 absolute
든 main
이 되지만 않는다면 잘 구동됨.
--> 결론, absolute path
를 애용하자. 땅땅!
__init__.py
파일의 역할에 대해서 정리-> __init__.py
란 폴더(디렉터리)가 패키지로 인식되도록하고, 패키지를 초기화하는 역할을 함.
즉, 임포트로 패키지를 가져오면 __init__.py
파일이 실행되므로 이 파일에서
from . import
모듈 형식으로 현재 패키지에서 모듈을 가져오게 만들어야 함.
※ 참고로 python3.3 버전부터는 init.py 파일이 없어도 패키지로 인식한다(PEP 420).
하지만 하위 버전 호환을 위해 init.py 파일을 생성하는 것이 안전한 방법이다.
-> __init__.py
파일 사용 예시
# app/a.py from Module import test # app/b.py from Module import test -> init.py 적용 init.py 파일에 한번만 정의해 두면 해당 디렉토리에서 test라는 함수를 공통적으로 사용할 수 있음 # app/__init__.py from Module import test