sys
도 import
해야하는 모듈이다. 파이썬은 sys
모듈의 위치를 어떻게 찾을 수 있을까?import sys
print(sys)
# <module 'sys' (built-in)>
sys를 import 해보면 bulit-in 모듈이라는 것을 직접 확인 할 수 있다.
bulit-in 모듈은 이미 파이썬에 포함되어 있기때문에 파이썬이 바로 쉽게 찾을 수 있다.
파일의 디렉토리가 이런식으로 구성되어있다고 가정한다면,
from package1 import module1 # module1의 바로 상위 파일은 package1 에서 받아온다.
from package1.module2 import function1 # package1에 있는 module1안에 있는 function1 을 받아온다.
from package2 import class1
from package2.subpackage1.module5 import function2
💡 프로젝트의 최상단 디렉토리를 기준으로 경로를 잡는다. 따라서 경로가 항상 동일하기 때문에 절대경로라고 부른다.
위 사진에서 현재 위치가 module3이라고 생각하고 class1과 function2를 사용하고 싶다면
# package2/module3.py
from . import class1
from .subpackage1.module5 import function2
이런식으로 지금 내가 있는 위치를 기준으로 파일을 찾아야 한다.
이때 .은 import가 선언되는 파일의 현재위치, ..은 현재위치에서 상위 디렉토리로 가는 경로
상대경로는 경로의 길이를 줄여줄 수는 있지만, 헷갈리고 파일위치가 변경되면 경로의 위치도 변경되어야 한다는 단점이 있기때문에 웬만하면 절대경로를 사용한다.
(init.py는 해당 디렉토리가 패키지임을 알려주는 역할)
파일경로가 위랑 같을때, main.py에서 상대경로로 add_and_mutiply를 import했을 때
from .calculator.add_and_multiply import add_and_multiply
# from .calculator.add_and_multiply import add_and_multiply
# ImportError: attempted relative import with no known parent package
다음과 같은 오류가 발생한다.
오류 메시지에서 보면 상대경로가 부모패키지를 가지고 있지 않다고 써있는데,
Note that relative imports are based on the name of the current module. 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의 이름은 항상__main__
이기 때문에 파이썬의 메인 모듈로서 사용하는 모듈을 항상 절대경로를 사용해야한다고 나와있다.
from calculator.add_and_multiply import add_and_multiply
# 5
처럼 절대경로로 바꾸어주면 module를 잘 불러와 사용이 가능하다.
add_and_multiply.py에서는 절대경로, 상대경로 둘다 import 하는데 문제가 없다.
그 이유는
main.py에서는 __name__ == '__main__'
때문에 항상 절대경로로 사용해야 했지만, 패키지 파일안에 있는 파일에서는 모듈의 이름이 __name__
으로 설정되지 않기 때문에 상대경로, 절대 경로 상관없이 둘다 사용할 수 있다.
1. import할때 경로의 총 길이 줄여주기
import pkg.mod1
pkg.mod1.func2()
현재 pkg에서 mod1, func2 라는 함수를 import 하여 사용하기 위한 기본 방법으로 func2 함수를 호출할때 마다 모든 경로를 다 타입해주어야하기 때문에 번거롭다. 그런데 만약에 함수 이름은 곧바로 호출 할 수 있으면 편할텐데, init.py을 통해 함수의 경로를 줄여줄 수 있다.
1) init.py파일에 import해줄 함수나 변수를 먼저 적어준다.
# __init__.py
from .mod1 import func2
2) 원하는 파일에 from ... import ... 형식을 통해서 사용 할 수 있다.
# main.py
from pkg import func2
func2()
2. 변수, 함수, 클래스 제한하기
모듈의 모든 함수를 다 외부로 노출시키지 않고,내부적으로만 사용할 수 있게 막는 것.
all 변수를 통해 정의 된다.
all 변수의 default 값은 모든 함수, 변수, 클래스이기 때문에 all 변수를 따로 정의해주어 import 될 수 있는 요소들을 제한 할 수 있다.
# __init__.py
from .mod1 import func2
from .mod2 import func3
__all__ = ['func2', 'func3']
init 파일에 외부로 노출되지 않도록 하고 싶은 함수 정의
# main.py
from pkg import *
func2()
func3()
func4() ## <== Error. func4 함수는 __all__ 에 정의되지 않았으므로 import 될 수 없음.
all 변수는 string 값을 가지고 있는 list이기 때문에 import 되기 원하는 요소들을 string으로 list에 선언해면 된다.