티스토리 뷰

카테고리 없음

Module, Import

xoxowo 2022. 6. 25. 15:52

Module과 Import

 

파일에 . py  확장자를 붙인 파이썬 파일은 모듈이라고 부르는데 (평소에는..편하게 파일이라고 얘기했다...) 파일 하나에 모든 내용을 담게 되면 프로그램이 길어짐에 따라 파일 버전 관리도 어려워지게 된다. 그래서 여러 개의 파일로 나눠 이 파일의 정의해둔 기능을 다른 파일에서 구현하려고 할 때 모듈(Module)을 임포트(import)한다고 한다. (메인 모듈은 최상위 수준에서 실행되는 스크립트나 계산기 모드에서 액세스하는 변수들의 컬렉션이다.)

 

예를들어  add 라는 함수를 정의한 파일을 plus_add.py로 저장하고 이 add 함수 기능을 play.py 파일에서 구현(사용)하고자 한다면 play.py 파일에서 다음과 같은 명령어로 import 한다. 

import plus_add

물론 모듈을 가져온다고해서 가져온 모듈의 코드가 실행되는 것은 아니며, 그냥 모듈 이름인 plus_add 만 들어가는 것이기 때문에 모듈 이름을 사용해서 함수를 구현해야한다.

# play.py 파일 내부에서 add 파일(모듈)을 임포트한다
import add

# 임포트한 add.py 모듈 내부의 정의 된 함수 ccc을 사용할 때 모듈이름을 사용하여 엑세스 한다
add.ccc(1, 2)

 

사용자가 import 문을 실행할 때 파이썬 인터프리터는 다음 차례로 검색한다.

1. sys.modules

2. built-in modules

3. sys.path

 

sys.modules

파이썬이 모듈이나 package를 찾기 위해 가장 먼저 확인하는 곳이며, 이미 import 된 모듈과 package들을 저장하고 있기 때문에 한 번이라도 import 된 모듈과 package는 다시 찾지 않아도 된다. 한번 호출된 모듈들을 딕셔너리 형태로 저장한다.

 

built-in modules (내장 모듈)

sys.modules에서 못찾았다면 다음으로 파이썬 공식 라이브러리에서 찾는다. Built-in 모듈들은 이미 파이썬에 포함되어 나오므로 파이썬이 쉽게 찾을 수 있다.

ex) 대표적으로 print() 함수가 있다.

 

sys.path

sys.modules,built-in modules에서 찾지 못한 모듈은  마지막으로 sys.path에 지정되어 있는 경로들을 확인해서 찾는다.

사용자 정의한  모듈을 찾는 곳이 sys.path 인데 sys.path는 경로가 srring으로 이루어진 리스트이다.

 

인터프리터가 위 세 공간에서도 모듈을 찾지 못하면  ModuleNotFoundError 에러를 리턴한다.


Absolute Path & Relative Path

 

절대 경로 (absolute path)

절대 경로는 매우 명확하게 모듈의 위치를 적기 때문에 어디서 어떤 모듈을 사용하고 있는지 쉽게 알 수 있다. 또한 import문의 위치가 변경되더라도 가져올 수 있다.

다만 경로 자체를 모두 기재해야 하기 때문에 코드가 길어질 수 있다는 단점이 있다.

from package1 import module1

# 패키지가 많아 경로가 길어질 수 있다
from package1.subpackage2.subpackage3.subpackage4.subpackage5.module5 import function6

상대 경로 (relative path)

상대 경로는 현재 위치, import 문이 있는 위치를 기준으로 가져올 리소스를 지정한다.

Relative path는 선언해야 하는 경로의 길이를 (코드의 길이) 줄여준다는 장점은 있지만 헷갈리기 쉽고 파일 위치가 변경되면 경로 위치도 변경되어야 하기 때문에 권장하진 않는다.

# 패키지 앞에 점(.)은 현재 작업중인 파일과 동일한 디렉토리에 있기 때문에 점(.) 하나만 사용한다
from .some_module import some_class
# 점이 두개는 현재 위치에서 한단계 상위 폴더라는 것을 의미한다
from ..some_package import some_function

파이썬에서는 경로 구분을 리눅스나 윈도즈처럼 슬래쉬나 백슬래쉬가 아니라 점(.)으로 구분한다.


python replit 57

 

 

 

 

 

 

여기서 main.py 파일은 calculator폴더 안에 있는 add_and_multiply.py 파일의 add_and_multiply 함수를 import 하고 있는데 이 calculator가 패키지이다.  이 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))
    
# 실행결과
from .calculator.add_and_multiply import add_and_multiply
ImportError: attempted relative import with no known parent package

ImportError 발생

main.py 파일 기준으로 상위 패키지가 없는데 상대 경로로 import를 해서 오류가 발생한 것인데 import 경로를 먼저 확인한다.

 

main.py 파일이 위치한 곳에서 상위 파일로 calulator 패키지가 없기 때문에 절대 경로를 사용하여 해당 패키지가 어디에 위치해있는지 파이썬 인터프리터에게 알려주면 된다.

# absoulte 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 모듈과 차이점을 생각해보고 결과를 출력해 보세요.

 

 

 

 

 

 

calculator 패키지 내부의 add_and_multiply.py 파일의 코드 내용이다.

import 구문을 살펴보면 모두 multiplication.py 의 multiply 함수를 임포트한다는 뜻인데 상대 경로 와 절대 경로 모두 사용해도

# 상대 경로 
from .multiplication import multiply

# 절대 경로 
from calculator.multiplication import multiply

def add_and_multiply(a,b):
    return multiply(a,b) + (a+b)
    
print(add_andm_multiply(1,2)

# 상대 경로로 import 후 실행결과
rom .multiplication import multiply
ImportError: attempted relative import with no known parent package

# 절대 경로로 import 후 실행결과
 from calculator.multiplication import multiply
ModuleNotFoundError: No module named 'calculator'

 

 

상대 경로로 import할 시 ImportError 발생

add_and_multiply.py가 __main__이 되므로 상대경로를 사용할 수 없게 된다.

 

절대 경로로 import할 시 ModuleNotFoundError 발생

No module named 'calculator'  calculator패키지가 있는데 왜 calculator이름이 없다고 오류가 나오는지 확인해보면

이미 이 add_and_multiply.py 파일이 calculator 내부에 있기 때문에 서로 import 할 시에는 모듈 명만 기재하면된다.

 

import 구문에서 calculator 패키지 명을 빼고 내부 모듈로 이름만 넣어 실행해보면 정상적으로 작동하는 것을 확인할 수 있다.

# from calculator.multiplication import multiply 에서 calculator(패키지명)을 삭제하고 실행
from multiplication import multiply

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

print(add_and_multiply(1,2))

# 실행결과
5

_ _init_ _. py

calculator 패키지 내부를 보면 내부가 비어있는 파일인 _ _init_ _. py 파일을 볼 수 있는데, 이 _ _init_ _. py는 왜 있는 것인가?

 

패키지를 읽을 때 어떤 처리를 수행하거나 패키지 내부의 모듈들을 한꺼번에 가져오고 싶을 때 패키지 폴더 내부에 _ _init_ _. py을 만들어 사용한다.

(위 calculator 패키지 파일 내부에도 _ _init_ _. py 폴더가 있는 것을 확인할 수 있다.)

이 파일에는 _ _all_ _이라는 이름의 리스트를 만드는데, 이 리스트에 지정한 모듈들이 from 패키지 이름 import * 를 할 때 전부 읽어 들여진다.

 

***python3.3 이전 버전에서는 __init__. py파일이 무조건 있어야 패키지로 작동했으나, 이후 버전에는 __init__. py 파일이 없어도 폴더 내부에 파이썬 파일이 들어있기만 하면 패키지로 작동한다고 

# 사용 시 읽어들일 모듈의 목록을 all 리스트 내부에 적어주면 된다

_ _all_ _ = ["module1", "module2", "module3" ...]

 

댓글