TIL - Python - modules&packages
# 'sys.modules'와 'sys.path'의 차이점
-
sys.modules
- 파이썬이 불러올(import) 모듈이나 package를 찾기 위해 가장 먼저 확인하는 곳
- dictionary 형태
- 이전에 불러왔던 모듈과 package가 저장돼 있음
- 새롭게 불러올 모듈과 package는 이 곳에서 찾을 수 없다.
-
sys.path
- 파이썬이 모듈과 package를 불러올 때,
sys.modules
와built-in modules
에 이어 마지막 순서로 확인하는 곳 - list 형태이며, 그 안의 string 요소들은 파이썬 모듈들이 저장된 경로를 나타냄
- 만약 sys.path 에서도 불러올 대상을 찾지 못하는 경우,
ModuleNotFoundError
에러를 리턴한다.
- 파이썬이 모듈과 package를 불러올 때,
-
sys
모듈을 불러올 수 있는 이유는?파이썬이
sys
모듈을 통해 불러올 모듈과 packge를 찾는다는 걸 알아봤다. 그렇다면sys
모듈 자체는 파이썬이 어떻게 찾을 수 있을까? 이를 이해하려면sys
모듈이 위치한 경로를 알아야 한다.sys
모듈은 파이썬의 내장 모듈로, 모듈의 경로 정보는 파이썬 설치 시 default 값으로 저장된 상태다. 저장된 경로를 통해 파이썬은sys
모듈을 찾아낸다.
# 'sys'모듈 이외의 파이썬 내장 모듈을 확인하고 싶다면... 아래의 메서드를 활용하자
import sys
print(sys.builtin_module_names)
# Absolute path와 Relative path의 차이점
-
Absolute path(절대 경로)
- 절대 경로는 import가 이뤄지는 경로와 상관없이 항상 경로가 동일하다.
- 절대 경로는 current directory(현재 프로젝트의 경로)부터 시작된다.
- 일반적으로 local package를 import 할 때는 absolute path가 사용된다.
- 입력한 경로의 길이가 길어지는 단점이 있다.
- 웬만하면 Absolute path 사용이 권장된다.
-
Relative path(상대 경로)
- 현재 프로젝트의 최상단 디렉토리가 아닌 import 하는 위치를 기준으로 경로를 정의한다.
- 일반적으로 local package 안에서 다른 local package를 import 할 때 사용된다.
- dot(
.
): import가 선언되는 파일의 현재 위치를 의미 - dot2개(
..
): 현재 위치에서 상위 경로로 이동 - 경로의 길이가 줄어드는 장점이 있지만, 파일 위치가 변경되면 경로 위치도 변경되어야 하는 단점이 있다.
# main module에서 패키지 모듈을 import할 때 주의할 점
- 아래 이미지와 똑같은 구조의 프로젝트 폴더를 생성해보자.
main.py
는 main module에 해당하며, 패키지 폴더 calculator는 내부에add_and_multiply.py
모듈과multiplication.py
모듈을 갖고 있다.
- 각각의 파일 내용은 다음과 같다.
# main.py
# absoulte path
# from calculator.add_and_multiply import add_and_multiply
# relative path
from .calculator.add_and_multiply import multiplication
if __name__ == '__main__':
print(add_and_multiply(1,2))
# 결괏값: ImportError: attempted relative import with no known parent package
# 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
# add_and_multiply.py
def multiply(a,b):
return(a*b)
- 위에서 main module에 해당하는
main.py
는 calculator패키지의 모듈을 import해서 실행시키고 있지만, error로 인해 코드가 정상 처리되지 않고 있다. error의 발생 원인은 경로 설정과 관련 있는데, 자세한 이유는 python 공식 문서를 통해 짐작할 수 있다.Since the name of the main module is always "main", modules intended for use as the main module of a Python application must always use absolute imports.
- 공식 문서에 따르면, main module에서 module을 불러와서 사용하려면 반드시 절대 경로를 사용해야 한다. 그 이유는 상대경로의 특성과 관련이 있다. 상대경로는 import가 이뤄지는 위치를 기준으로 경로를 정의하는데, 모듈을 스크립트에서 직접 실행하면(
__name__
==__main__
이 되면) 모듈의 이름이__main__
이 되면서 상대경로의 기준점이 바뀌게 된다.(relative import 시, 현재 모듈의 이름이 다렉토리의 기준이 되기 때문이다.) 경로의 기준점이 바뀌게 되면, 불러올 모듈을 제대로 찾을 수 없기 때문에 절대경로를 지정하여 경로의 기준점 변환에 상관없이 모듈을 import하도록 해야 한다.
# main.py
# absoulte path
from calculator.add_and_multiply import add_and_multiply
# relative path
# from .calculator.add_and_multiply import multiplication
if __name__ == '__main__':
print(add_and_multiply(1,2))
# 결괏값: 5
-
if __name__ == '__main__':
은 무엇을 의미할까?-
파이썬에서 모듈을 실행하는 방법엔 크게 두 가지가 있다. 하나는 인터프리터에서 직접 실행하는 것이고, 다른 방법은 실행할 모듈을 다른 모듈에서 import하여 실행하는 것이다.
-
직접 실행하는 경우
python3 add_and_multiply.py
-
다른 모듈에서 import하여 실행하는 경우
from calculator.add_and_multiply import add_and_multiply
add_and_multiply()
-
-
1번의 경우 모듈
add_and_multiply.py
의__name__
이라는 변수에__main__
할당된다. 반면 2번처럼 import하는 경우엔__name__
변수에 모듈 이름인 add_and_multiply가 할당된다. 결국if __name__ == '__main__':
의 의미는 모듈을 인터프리터로 직접 실행했을 경우에만if문
내부의 코드를 실행하라는 의미이다.
-
# add_and_muliply.py에서 multiply함수를 절대경로와 상대경로로 각각 import 해보기
- 상대경로로 불러왔을 경우
from .multiplication import multiply
# from multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
# 결괏값: ImportError: attempted relative import with no known parent package
- 절대경로로 불러왔을 경우
# from .multiplication import multiply
from multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
# 결괏값은 없지만, 함수가 정상적으로 실행됨
# '__init__
.py' 파일의 역할
-
__init__.py
는 해당 디렉터리가 패키지로 인식되도록 도와주는 역할을 한다. -
Import할 때 경로의 총 길이 줄여주는 역할을 한다.
-
__init__.py
를 활용해서 import할 수 있는 변수/함수/클래스를 제한할 수 있다.
# __init__.py
from .multiplication import multiply
__all__ = ['multiply']
# import 할 수 있는 함수를 multiply()로 제한
from calculator import *
add_and_multiply()
# multiply()
# 결괏값: NameError: name 'add_and_multiply' is not defined
- 패키지가 import 될 때 꼭 먼저 실행되어야 하는 코드들을 관리함.
Author And Source
이 문제에 관하여(TIL - Python - modules&packages), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@fcfargo/TIL-Python-modulespackages저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)