모듈을 모아놓은 이유
1. 다른 파일에서 재사용이 가능
2. 전체 코드가 한 파일에 넣기에는 너무 커졌을 때 나누어서 정리하기 위함
my_list = [1, 2, 3, 4, 5]
my_list_length = len(my_list)
# len은 파이썬이서 이미 모듈로 구현해놓음
모듈 만들기
재사용 하고 싶은 함수, 클래스, 변수를 구현한 후 파일로 생성 후 import 키워드를 통해 사용
## my_module.py
my_module_var = 7
def my_module_func()
return 'hello!'
class MyModuleClass:
pass
모듈 사용하기
## import my_module
import my_module # import 모듈명
print(my_module.my_module_var()) # <모듈명>.<사용 변수/함수/클래스명>
my_module.my_moudle_func()
my_module_class = my_module.MyModuleClass()
from my_module import my_module_func, my_module_var
print(my_module_var)
my_module_func()
import my_module as m1
m1.my_module_func()
일반 모듈처럼 import하여 사용할 수 있으며, dot을 이용하여 해당 패키지의 원하는 모듈을 import해야 함
import pkg.mod1
from pkg.mod2 import func2
pkg.mod1.func2()
func2()
Package Initialization
package의 import 시 초기 설정을 진행할 때 파이썬에서는 __init__
.py 파일을 통해 이를 가능하게 해줌
package에 __init__
.py 파일이 있을 경우 패키지의 import 시 __init__
.py 파일의 코드들이 자동적으로 실행
__init__
.py의 역할
- Import 할 때 경로의 총 길이 줄여주기
- 패키지에서 import할 수 있는 변수/함수/클래스 제한
- 그 외 package가 import될 때 꼭 먼저 실행되어야 하는 코드들
import pkg.mod1
pkg.mod1.func2() # 너무 길기 때문에 줄여보자
----------------------------------
# __init__.py # ``__init__``.py 파일에 한번 import!
from mod1 import func2
#main.py
from pkg import func2
func2()
# __init__.py
from mod1 import func2
from mod2 import func3
__all__ = ['func2', 'func3']
#main.py
from pkg import func* # func는 권장하지 않음
func2()
func3()
func4() # func4함수는 정의되지 않았으므로 import 될 수가 없음
파이썬에서는 sys.modules ----> built-in modules ----> sys.path 순으로 검색
단순 dictionary 형태이며 이미 import된 모듈과 패키지를 저장하고 있어 한 번 import되면 따로 다시 찾지 않아도 되나, 새로 import하는 모듈, 패키지는 확인이 불가능함
import sys
print(sys.modules)
>>>
{'sys': <module 'sys' (built-in)>,
'builtins': <module 'builtins' (built-in)>,
'_frozen_importlib': <module '_frozen_importlib' (frozen)>,
'_imp': <module '_imp' (built-in)>,
'_warnings': <module '_warnings' (built-in)>,......}
파이썬에 이미 포함되어 있는 공식 라이브러리들
<module 'sys' (built-in)>
#sys 모듈은 이미 파이썬 설치시 포함되어 있는 모듈임
import sys
print(sys.path)
>>>
['/home/soohyung/PycharmProjects/untitled',
'/home/soohyung/PycharmProjects/untitled',
'/usr/lib/python38.zip',
'/usr/lib/python3.8',
'/usr/lib/python3.8/lib-dynload',
'/home/soohyung/PycharmProjects/untitled/venv/lib/python3.8/site-packages',
'/home/soohyung/PycharmProjects/untitled/venv/lib/python3.8/site-packages/setuptools-40.8.0-py3.8.egg',
'/home/soohyung/PycharmProjects/untitled/venv/lib/python3.8/site-packages/pip-19.0.3-py3.8.egg'
]
프로젝트의 최상단 디렉토리를 기준으로 경로를 지정하는 방식으로 import 하는 파일이나 경로에 상관 없이 항상 경로가 동일함
위 그림에서 절대 경로를 통해 module5를 import하려면 아래의 경로로 가야함
my_app / package2 / subpackage1 / module5.py
파이썬에서는 slash 대신 dot을 통해 경로를 표현함
my_app.package2.subpackage1.module5.py
my_app은 이미 프로젝트 안에 있어 생략하고 from import를 이용하면 아래와 같음
from my_app.package2.subpackage1.module5 import function1
상대 경로는 import하는 위치를 기준으로 경로를 정의하고 있으며 절대 경로의 사용 시 경로가 길어질 수 있는 단점을 보완하기 위해서 사용이 가능함
package2/module3에서 subpackage1의 module5를 import하려면,
# package2/module3.py
from .subpackage1.module5 import fuction2
# subpackage 앞의 dot은 현재 위치를 의미함
subpackage1/module5에서 module4를 import하려면,
#subpackage1/module5
from ..module4 import class4
# 상위 위치로 이동하기 위해서는 double dot(..)을 이용함
그러나, 상대 경로를 사용하면 헷갈리기 쉬우며, 파일 위치의 변경 시 경로 위치도 변경되어야하는 단점이 있어 절대 경로의 사용이 권장
# mod1.py
def func1(a, b):
return a * b
# mod2.py
def func2(a, b):
return a + b
# __init__.py
from pkg.mod1 import func1 #== from .mod1 import func1(상대경로)
from pkg.mod2 import func2 #== from .mod1 import func2(상대경로)
# main.py
from pkg import func1
from pkg import func2
a = func1(2, 3)
b = func2(2, 3)
print(f"""{a}, {b}, {a * b}""")
>>> 6, 5, 30