패키디 디렉토리 구조
아래와 같은 구조 생성
main.py
# absoulte path
#from calculator.add_and_multiply import add_and_multiply
# relative path
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)
__init__.py (파일만 생성)
위 대로 파일을 구성하고 main.py를 실행시켜보면 Error를 보여준다.
에러를 보이는 이유는 처음 실행되는 파일의 name은 __main__이 된다.
공식문서에서 보면 기본 모듈(실행한 파일)에서 사용하려는 모듈은 항상 절대경로로 가져와야 한다고 한다.
# absoulte path
from calculator.add_and_multiply import add_and_multiply
# relative path
#from .calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(add_and_multiply(1,2))
기본 모듈은 절대 경로로 가져오도록 수정
결과
add_and_multiply.py에서 multiply함수를 절대경로와 상대경로도 각각 임포트 해보고 main 모듈과 차이점을 생각해보고 결과를 출력해 보세요.
위 문제의 차이점을 알기위해 코드를 조금 추가해 보자
from .multiplication import multiply
# from calculator.multiplication import multiply
def add_and_multiply(a, b):
print(f"add_and_multiply.py = {__name__}")
return multiply(a, b) + (a+b)
OR
# from .multiplication import multiply
from calculator.multiplication import multiply
def add_and_multiply(a, b):
print(f"add_and_multiply.py = {__name__}")
return multiply(a, b) + (a+b)
둘중 어느것을 해도 실행이 된다.
main.py도 수정
# absoulte path
#from calculator.add_and_multiply import add_and_multiply
# relative path
from calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(f"main.py = {__name__}")
print(add_and_multiply(1, 2))
결과!!
결과를 보면 확연한 차이가 있다.
둘다 print(__name__) 했지만
main.py = __main__
add_and_multiply.py = calculator.add_and_multiply
이렇게 결과물이 나뉜다.
즉 기본 모듈은 main.py로 실행되었으며 이 파일이 기본 모듈이다.
기본 모듈은 다른 페키지나 모듈을 불러올때 절대경로로 불러와야 하며 기본 모듈이 아닌경우는 절대경로든 상대경로든 상관이 없다.
__init__.py 의 역활
1. __init__.py 파일은 해당 디렉터리가 패키지의 일부임을 알려주는 역할을 합니다
2. 디렉터리에 __init__.py 파일이 없다면 패키지로 인식되지 않을 수도 있습니다.
3 3.3부터는 __init__이 없어도 인식한다고 합니다.
__all__
- 특정 디렉터리의 모듈을 *를 이용하여 import할 때에는 다음과 같이 해당 디렉터리의 __init__.py 파일에 __all__이라는 변수를 설정하고 import할 수 있는 모듈을 정의해 주어야 합니다.
- __all__로 정의하지 않으면 인식되지 않습니다
예를들어 봅시다.
calcpkg를 import 할때 아래 패키지중(operation,geometry) operation안의 element.py 함수중 mul과
geometry 안의 vector.py에서 dot 함수만 공개를 하고 싶을때 __all__값을 항당하여 특정 함수만 공개를 할려고 한다.
다음과 같이 __init__.py를 수정한다
# calcpkg/__init__.py
__all__ = ['mul', 'dot'] # calcpkg 패키지에서 add, triangle_area 함수만 공개
from .operation import * # 현재 패키지의 operation 모듈에서 모든 변수, 함수, 클래스를 가져옴
from .geometry import * # 현재 패키지의 geometry 모듈에서 모든 변수, 함수, 클래스를 가져옴
from calcpkg import * # calcpkg 패키지의 모든 변수, 함수, 클래스를 가져옴
print(add(1, 2)) # 에러: add 함수는 공개되어 있지 않으므로 사용할 수 없음 #
print(mul(1, 2)) # mul 함수는 공개되어 있으므로 사용할 수 있음
print(triangle_area(3, 4)) # 에러 : triangle_area 함수는 공개되어 있으므로 사용할 수 없음
print(rectangle_area(3, 4)) # 에러: rectangle_area 함수는 공개되어 있으므로 사용할 수 없음
결과
Traceback (most recent call last): File "C:\project\main.py", line 4, in <module> print(mul(1, 2)) # 에러: add 함수는 공개되어 있지 않으므로 사용할 수 없음 NameError: name 'add' is not defined
'Python' 카테고리의 다른 글
[Python] 이터레이터(Iterator) (0) | 2020.06.27 |
---|---|
[Python] 제너레이터(generator) (0) | 2020.06.27 |
[Python] Sys modules (0) | 2020.06.25 |
[Python] funciton of arguments, parameter (0) | 2020.06.24 |
[Python] pygame 으로 벽돌깨기 만들기 part-7 (0) | 2020.05.25 |
댓글