[Python] 2_Module

dev.soo·2020년 8월 24일
0

Python

목록 보기
1/6
post-thumbnail

Modules and package

모듈(Module)은 파이썬 코드를 논리적으로 묶어서 관리하고 사용할 수 있도록 하는 것으로, 보통 하나의 파이썬 .py 파일이 하나의 모듈이 된다. 모듈 안에는 함수, 클래스, 혹은 변수들이 정의될 수 있으며, 실행 코드를 포함할 수도 있다.

모듈은 Python 기본 라이브러리에 저장된 내장 모듈, 사용자가 작성한 로컬 모듈, 외부에서 pip 를 사용해 install 한 외부 모듈이 있다.

Importing modules and packages

Python 은 모듈이나 패키지를 불러올 때 아래의 순서대로 모듈을 탐색한다.

  1. sys.modules : import 되어 로딩되어 있는 모듈
  2. built in modules : Python 내장 모듈 (Python 공식 라이브러리)
  3. sys.path : Python 라이브러리가 설치되어 있는 디렉토리

sys.modules 는 한 번 import 된 모듈들이 dictionary 로 저장되어 있어 한 번 import 된 모듈은 파이썬이 다시 찾지 않아도 된다.

반면 sys.path 모듈은 리스트의 처음부터 마지막까지 찾다가 도중에 찾으면 탐색을 멈추고, 찾지 못하면 ModuleNotFoundError 를 낸다. sys.path 는 list 로 되어 있으므로 내용을 추가하거나 삭제할 수 있다.

sys 는 시스템과 관련된 정보를 가지고 있는 모듈로, Python library 에 저장된 표준모듈이다. 따라서 Python library 에서 built-in modules 를 찾아 import 한다.

이처럼 Python 에서 모듈을 import 할 때, built-in modules 와 pip 로 import 된 외부 모듈은 자동으로 site-packages 에 저장되기 때문에 python 이 쉽게 찾아낼 수 있다. local package or module 은 import 시 디렉토리를 정확하게 입력해야 한다.

Absolute & relative path while importing modules

디렉토리는 working file이 포함된 directory 와 상관 없이 사용하고자 하는 모듈의 최상단 부모 directory 부터 순차적으로 경로를 서술해주는 방식이 있다. 이는 Absolute path 로, 정확한 위치를 알려줄 수 있지만 경로가 너무 길어질 수 있다는 단점이 있다.

반면 Relative path 는 import 하는 위치(working area)를 기준으로 경로를 정의한다. 그래서 일반적으로 local package 안에서 다른 local package를 import 할 때 사용한다.

Package 만들어 보기

위와 같이 directory 를 만들고, main.py 에 아래와 같이 relative path 를 사용하여 모듈을 import 하였다.
# 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))

그랬더니 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.

name 이 __main__으로 되어 있는 모듈에서 패키지의 다른 모듈을 import 하기 위해서는 항상 absolute path 를 사용해야 한다.

따라서 아래와 같이 import 경로를 수정해 주었다.

# inside main.py 
# relative path
from .calculator.add_and_multiply import add_and_multiply

if __name__ == '__main__':
    print(add_and_multiply(1,2))
    
    
결과 : 5

이처럼 main.py 가 main module 일 때 (__name__ = "__main__" 일 때) 다른 모듈을 import 하기 위해서는 절대 경로를 활용했다. 반면, main.py 가 main module 이고 여기서 import 되는 다른 module 에서 다른 module 을 불러 올 때는 절대경로와 상대경로를 다 사용할 수 있다.

1. 절대경로 사용하기

< main.py - main module 내부>

from calculator.add_and_multiply import add_and_multiply # 절대경로 

if __name__ == '__main__':
    print(add_and_multiply(1,2))

main 모듈에서 import 되는 add_and_multiply.py 내부

from calculator.multiplication import multiply #절대경로

def add_and_multiply(a,b):
    return multiply(a,b) + (a+b)
    

2. 상대경로 사용하기

< main.py - main module 내부>

from calculator.add_and_multiply import add_and_multiply # 절대경로 

if __name__ == '__main__':
    print(add_and_multiply(1,2))

main 모듈에서 import 되는 add_and_multiply.py 내부

from .multiplication import multiply #상대경로

def add_and_multiply(a,b):
    return multiply(a,b) + (a+b)
    

두 방법 다 잘 작동한다.




__init__.py

아까 만든 패키지의 구성을 다시 살펴보면,

calculator 디렉토리 안에 __init__.py 라는 파일을 만들었다. 이 파일은 아래와 같은 기능을 갖는다.

  1. calculator directory 가 python package로 인식될 수 있도록 해준다.
  2. package 를 초기화 해준다(initialize)
  3. __init__.py 파일 안의 내용은 자동으로 main module 에서 실행된다.
    ex. __init__.py 내부에 print("Hello") 가 있으면,
    main module 에서 자동으로 출력됨.
  4. __init__.py__all__= [ ] 에서 사용 시 읽어 들일 모듈의 목록을 리스트 안에 작성하면 패키지를 읽어 들일때 해당 모듈이 import 된다.

0개의 댓글