개인 공부 후 자료를 남기기 위한 목적이므로 내용 상에 오류가 있을 수 있습니다.
1월 30일(일)
Import Search 순서
' abc '라는 package를 사용하려면 다음처럼 import를 해야한다.
import abc
여기서 abc는 단순한 파이썬 파일(모듈)이거나, 파이썬 파일들을 담고 있는 디렉토리(package)이다.
그러므로 해당 파일이나 디렉토리가 어디에 있는지를 파이썬이 찾을 수 있어야만 import를 할 수 있다.
파이썬은 다음의 3가지 장소를 순서대로 보면서 모듈/package를 찾는다.
- sys.modules
- built-in modules
- sys.path
sys.modules
파이썬이 모듈이나 package를 찾기 위해 가장 먼저 확인하는 곳이다.
sys.modules는 단순한 dictionary 이며, 이미 import된 모듈과 package들을 저장하고 있다.
즉, 한번 import된 모듈과 package들은 파이썬이 다시 찾지 않도록 기억하는 기능을 가지고 있다.
그러므로, 새롭게 import 하는 모듈 및 package는 sys.modules에서 찾을 수 없다.
built-in modules
파이썬에서 제공하는 파이썬 공식 라이브러리들이다.
built-in 모듈들은 이미 파이썬에 포함되어 나오므로 파이썬이 쉽게 찾을 수 있다.
sys.path
파이썬이 모듈/package를 찾을 때 가장 마지막으로 보는 장소가 sys.path이다.
sys.path는 기본적으로 list이며, string 요소들을 가지고 있는 list이다.
참고로, 각 string 요소들은 아래의 예시처럼 경로를 나타낸다.
즉, 파이썬은 list의 각 경로를 하나씩 확인하면서 해당 경로에 import 하고자 하는 package가 위치해 있는지 확인한다.
참고로, sys는 파이썬에 포함되어 있는 모듈이며 sys 모듈을 import해서 사용할 수 있다.
(단, sys 모듈의 위치를 찾고자 한다면 sys 모듈을 import 하고 print문으로 sys.modules를 출력해보면 된다.)
정리하자면, 파이썬은 import하고자 하는 모듈과 package를 찾을 때에 먼저 sys.modules을 보고 없으면 파이썬 built-in 모듈들을 확인한다. 그럼에도 없다면 마지막으로 sys.path에 저장되어 있는 경로들을 확인해서 모듈/package를 찾는다. 단, sys.path에서도 못찾으면 ' ModuleNotFoundError ' 에러를 리턴한다.
Absolute path VS 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
Absolute path는 이름처럼 절대경로를 의미한다.
그 이유는 import를 하는 파일이나 경로에 상관없이 항상 경로가 동일하기 때문이다.
다음과 같은 프로젝트를 예로 들어보면,
my_app 이라는 프로젝트는 package1과 package2라는 2개의 package를 가지고 있다.
그리고 package2는 subpackage2라는 충첩 package를 가지고 있다.
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 프로젝트의 가장 최상위 디렉토리에서 시작하는 것을 볼 수 있다.
단, 이미 my_app 프로젝트 안에 있기 때문에 my_app은 생략한 것이다.
(ex. 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를 사용한다.
하지만, Absolute path를 사용하면 경로가 길어질 수 있다는 단점이 존재한다.
Relative path
Relative path는 Absolute path와 다르게 프로젝트의 최상단 디렉토리를 기준으로 경로를 잡는게 아니라 import 하는 위치를 기준으로 경로를 정의한다. 그래서 일반적으로 Relative path는 local package 안에서 다른 local package를 import 할 때 사용한다.
예를 들어, package2의 module3에서 package2의 class1과 package2의 하위 package인 subpackage1에 있는 module5의 function2 함수를 import 하려고 한다면 다음 처럼 할 수 있다.
# package2/module3.py
from . import class1
from .subpackage1.module5 import function2
여기서 dot(.)은 import가 선언되는 파일의 현재 위치를 의미한다.
현재 위치는 package2/module3.py 이므로 현재 위치에서부터 원하는 모듈의 경로만 선언해주면 된다.
참고로, dot(.) 2개를 사용하면 현재 위치에서 상위 디렉토리로 가는 경로를 의미한다.
Relative path는 선언해야 하는 경로의 길이를 줄여준다는 장점은 있지만, 헷갈리기 쉽고 파일 위치가 변경되면 경로 위치도 변경되어야 하는 단점이 있다. 그러므로 웬만한 경우에는 Absolute path를 사용하는 것을 권장한다.
추가내용
1. main.py
다음의 calculator 패키지를 참고해보자.
main.py에서 상대경로로 add_and_multiply를 import 할 경우에 다음과 같은 에러가 발생한다.
# ImportError: attempted relative import with no known parent package
이러한 에러가 발생하는 이유는 다음과 같다.
메인 모듈의 이름은 항상 __main__ 이며, 일반적으로 프로젝트의 루트에 존재하기 때문에 찾을 부모 디렉토리가 없어서 Relative path로 import를 하면 에러가 발생한다. 즉, 메인 모듈은 항상 Absolute path로 import를 해야 한다.
참고로, 메인 모듈이 아닌 그 이외의 파일에서는 절대경로/상대경로 모두 import를 할 수 있다.
2. __init__.py 역할
- 해당 파일이 존재하는 디렉토리가 패키지임을 알려준다.
- 공통으로 적용가능한 기능이나 모듈을 포함하여 한 번의 선언으로 해당 경로의 위치한 모든 파일들이 이를 이용할 수 있게 한다.
- 필요에 따라 import 경로의 길이를 짧게 할 수 있다.
- __all__ 변수를 사용하여, import 할 수 있는 변수·함수·클래스를 제한할 수 있다.
'기타' 카테고리의 다른 글
TIL - 22.02.01 (0) | 2022.02.02 |
---|---|
TIL - 22.01.31 (0) | 2022.01.31 |
TIL - 22.01.29 (0) | 2022.01.29 |
TIL - 22.01.28 (0) | 2022.01.29 |
TIL - 22.01.27 (0) | 2022.01.27 |
댓글