상세 컨텐츠

본문 제목

[python]패키지, 모듈

언어/Python

by moonionn 2021. 3. 18. 17:25

본문

아래는 코딩테스트를 풀 때 가장 많이 쓰는 코드 중 하나입니다.

from sys import stdin
input = stdin.readline

 

이 코드는 현재 파일에 sys.stdin 모듈을 불러오는 코드입니다.

 

모듈은 개발과정에서 필수불가결한 존재입니다.

다른사람이 짠 코드를 내 코드와 융합해 사용할 수 있게 할 뿐 아니라

유지보수적인 관점에서도 아주아주 핵심적인 역할을 합니다.

그렇다면 파이썬은 이 모듈을 어떤 식으로 불러오는 걸까요?

 


모듈을 import하는 과정

우선 파이썬에서 모듈을 import 했을때

해당 모듈을 찾아가는 과정을 알아보고자 합니다.


1. sys.modules

sys의 modules는 import된 모듈들을 딕셔너리 형태로 저장합니다.

따라서 모듈 import시 먼저 sys.modules에 해당 모듈이 있는지 확인하는 과정을 거칩니다.

일종의 캐시메모리같은 역할을 하는 셈이죠.

math 모듈 import 전 sys.modules 내용. math관련 정보는 저장되어있지 않다.
math 모듈 import 후 다시 불러오면 해당 모듈과 관련된 디렉토리가 추가되어있다.


2. built-in modules

sys.modules에 없다면 파이썬 라이브러리에서 모듈을 찾습니다.

방금 위에서 math 모듈을 import 할때도

처음에 sys.modules에 해당 모듈정보가 있는지 확인했을 겁니다.

하지만 저장된 게 없었으니 built-in-modules 라이브러리에서 불러왔을 겁니다.

바로 위의 이미지를 보면 이런 string이 저장되어 있네요!

'math': 
<  module 'math' from 
   '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/lib-dynload/math.cpython-38-darwin.so'
>

 

sys 모듈도 마찬가지입니다.

'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>

 

그런데 앞의 math 모듈과 directory 표기방식이 조금 다른 이유는

sys 모듈 자체가 파이썬의 빌트인이라 그렇습니다.

파이썬 내장모듈 inspect로 이를 확인할 수 있습니다.

import inspect
inspect.getfile(math)

math 모듈 파일의 디렉토리

import inspect
inspect.getfile(sys)

sys파일은 built-in 모듈이라 에러가 난다.


3. sys.path

하지만 우리는 빌트인 모듈 외 여러 다양한 사용자 정의 모듈을 사용합니다.

이런 사용자 정의 모듈을 찾는 곳이 바로 sys.path입니다.

아래처럼 같은 디렉토리에 파일 두 개가 있습니다.

main.py 파일이 module_b를 모듈로 불러올 것입니다.

# main.py의 내용

from module_b import func

 

그런 다음 sys.path에 어떤 변화가 생겼는지 봅시다.

맨 윗줄에 해당 모듈의 path가 생성되었습니다.

이처럼 sys.modules에도 없고 built-in modules에도 없는 모듈 디렉토리는

sys.path에 저장됩니다.

import sys
print(sys.path)

#결과
[
  '/Users/moonimooni/Desktop/Web/wecode/python', 
  '/Users/moonimooni/.vscode/extensions/ms-python.python-2020.6.91350/pythonFiles', 
  '/Library/Frameworks/Python.framework/Versions/3.8/lib/python38.zip', 
  '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8', 
  '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/lib-dynload', 
  '/Users/moonimooni/Library/Python/3.8/lib/python/site-packages', 
  '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages'
 ]

 


__init__.py : 패키지화

모듈을 만들었으면 해당 모듈을 import해줄 준비를 해줘야 합니다.

이 과정이 없으면 아무리 다른 파일에서 해당 모듈을 불러오려 해도 에러가 납니다.

(예시: unresolved import 'module_a')

 

따라서 패키지화 해줄 디렉토리에 __init__.py 라는 파일을 만들어 저장해놓습니다.

코드 내용은 없지만, 그 존재 자체가 중요한 파일입니다.

cal/__init__.py 가 있어야 cal 디렉토리가 패키지화된다.

 


모듈을 불러오기 위한 path 작성방법

모듈을 불러올때 해당 모듈의 위치를 알려주는 두 가지 방법이 있습니다.

하나는 절대경로를 알려주는 것이고, 하나는 상대경로를 알려주는 것이죠.

둘을 구분하는 방법은 간단합니다.

path 앞에 쩜(.)이 붙으면 상대경로, 쩜이 없으면 절대경로입니다.


상대경로

파이썬에서 상대경로를 쓰는 방식은

리눅스를 썼던 사람들이라면 금방 익숙해질 형태를 띱니다.

대신 하위디렉토리를 나타내는 '/' 나 '\'를 '.'으로 대체합니다.

.folder.file_1 #현재 파일위치에 있는 folder라는 폴더의 file_1 소환

..parent_folder.file_2 #현재 파일위치보다 한단계 상위 디렉토리에서 file_2 소환

 

예를 들어, cal 내부의 디렉토리의 모듈들끼리 서로 상대경로를 써 import 해보면,

아래와 같습니다. 그리고 이 코드는 파일을 실행시키는 데 아무 문제가 없습니다.

# add_and_mul 파일 내용

from .mul import multiply

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

절대경로

결론부터 말하자면, 메인 모듈 (main.py)에서 모듈을 불러올때는 

무조건 절대경로를 사용해야 합니다.

(main 모듈에는 항상 아래와 같은 코드가 붙습니다.)

if __name__ == '__main__':
    #실행 코드

 

파이썬 프로그램을 처음 실행할 때  이 메인모듈이 첫 스타트를 끊습니다. 

따라서 메인모듈 내부에서 절대경로를 통해 sys.path에 

해당 프로그램의 절대경로를 입력, 저장해줘야 하고,

이 과정이 없다면, 뒤에서 줄줄이 호출될 예정인 모듈들의 상대경로를 찾지 못하게 됩니다.

main 모듈에서 상대경로를 쓰면 아래와 같은 에러가 발생합니다.

# ImportError: attempted relative import with no known parent package

 

main.py에서 절대경로로 다른 모듈을 import 한 뒤

sys.path에는 아래의 경로정보가 저장됩니다.

'/Users/moonimooni/Desktop/Web/wecode/python'

python 폴더가 절대경로의 기준이 된다.

 

관련글 더보기

댓글 영역