1. sys.modules
2. built-in modules
3. sys.path
import sys
print(sys.modules) # 불러왔던 모든 모듈들을 확인할 수 있다.
import sys
print(sys.path) # 리스트 형태로 지정되어 있는 경로를 확인할 수 있다.
✅ 위의 내용들을 바탕으로 sys.modules와 sys.path의 차이점을 살펴보면,
✅ 위에서 sys.modules와 sys.path를 호출할 때 sys 모듈을 import 해야 출력이 가능했었다. sys 또한 모듈이기 때문에 import 해야하기 때문이다. 그렇다면 sys 모듈의 위치는 어떻게 찾을 수 있을까 ?
import sys
for name in sys.builtin_module_names:
print(name)
📝 파이썬 정상적으로 설치가 되었다면 Built-in 모듈의 import는 문제가 없다. 그리고 pip
로 설치한 외부 모듈은 자동으로 site-packages
라는 디렉토리에 설치가 되고, 이 site-packages
는 sys.path
에 이미 포함되어 있기 때문에 import할 때 문제가 없다.
그러나 사용자가 직접 개발한 local package를 import 할때는 해당 package의 위치에 맞게 import 경로를 적절하게 지정해줘야 한다.
Local package를 import 하는 경로에는 absolute path 와 relative path 가 있다.
# 경로의 시작점이 모두 최상단 디렉토리이다.
from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1.module5 import function2
# package2/module3.py
from . import class1
from .subpackage1.module5 import function2
✅ Absolute path와 relative path의 차이점을 정리해보면,
👉 각각의 장단점이 있으나, Absolute path의 사용이 권장되어 진다.
👉 아래와 같은 디렉토리 구조를 가지고 있는 패키지를 만들어보았다.
# main.py 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_mutiply
를 임포트 했을 때 발생하는 에러는? main module 에서는 패키지의 모듈을 어떻게 임포트 해야하는가?
# relative path
from .calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(add_and_multiply(1,2))
#ImportError: attempted relative import with no known parent package
#absolute path
from calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(add_and_multiply(1,2)) # 5
✅ add_and_multiply.py
에서 multiply
함수를 절대경로와 상대경로도 각각 임포트 하였을때 main 모듈과 차이점은?
#상대경로
from .multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
print(add_and_multiply(1,2))
#ImportError: attempted relative import with no known parent package
#절대경로
from calculator.multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
print(add_and_multiply(1,2))
#ModuleNotFoundError: No module named 'calculator'
#절대경로
from multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)
print(add_and_multiply(1,2)) # 5
❗ add_and_multiply.py
에서 상대경로와 절대경로로 임포트 하기 직전에는 둘 다 작동이 잘 될것이라 예상했었다. 절대경로는 바로 위의 코드로 해결했다지만 상대경로는 왜 실행이 되지 않은 것일까? 이를 알아내기 위해 __name__
변수의 역할과 이를 활용해야 했다.
✅ __name__
변수의 역할은?
__name__
은 import로 모듈을 가져왔을 때 모듈의 이름이 들어가는 변수이다. 위의 calculator 패키지의 main.py 에 작성되어 있는 코드를 보면 __name__
변수에 __main__
이 있으면 출력을 실행하라는 조건문이 있다. 절대경로 지정을 통해 정상적으로 실행이 됐었고 이는 main.py 가 메인모듈(__main__
)이었다는 뜻이다.__name__
변수를 활용하면 임포트하는 모듈들의 __name__
을 알 수 있다. 📝 내 의문을 해소하고자 아래와 같이 calculator 폴더에 test.py 라는 파일을 추가하고 약간의 코드 변경을 하고 실행해보았다.
#multiplication.py
def multiply(a,b):
print(__name__)
return(a*b)
#test.py
from add_and_multiply import add_and_multiply
def test():
print(__name__)
print(__name__)
#출력값
"""
add_and_multiply
multiplication 👈
5
add_and_multiply.py __name__: add_and_multiply 👈
__main__ 👈
"""
#add_and_multiply.py
from multiplication import multiply
def add_and_multiply(a,b):
print(__name__)
return multiply(a,b) + (a+b)
print(add_and_multiply(1,2))
print('add_and_multiply.py __name__:', __name__)
#출력값
"""
__main__ 👈
multiplication 👈
5
add_and_multiply.py __name__: __main__ 👈
"""
__name__
은 __main__
으로 설정된다는 것이다. 그러나 모듈을 임포트해서 사용하면 임포트 된 모듈의 name은 원래의 모듈 이름으로 설정됨을 확인하였다. (위의 예시에서 multiplication.py 모듈은 test, add_and_multiply 모듈에서 __name__
이 모두 multiplication 으로 출력 되었다.)if name == 'main':
조건문을 사용하는 블록은 다른 파일에서 임포트하여 사용할때 실행되지 않는다.✅ __init__.py
파일의 역할은?
__init__.py
파일이 자동으로 실행한다.📝 reference
https://docs.python.org/3/tutorial/modules.html#intra-package-references