본문 바로가기
Python

[Python] 패키지 생성 실습

by UnoCode 2020. 6. 26.

패키디 디렉토리 구조

 

 

아래와 같은 구조 생성

 

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__이 된다.

https://docs.python.org/3/tutorial/modules.html#intra-package-references

 

공식문서에서 보면 기본 모듈(실행한 파일)에서 사용하려는 모듈은 항상 절대경로로 가져와야 한다고 한다.

 

# 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__로 정의하지 않으면 인식되지 않습니다

https://dojang.io/mod/page/view.php?id=2450

 

예를들어 봅시다.

 

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

댓글