modules & package

최창환·2022년 3월 7일
0
post-thumbnail

sys.modules

단순한 dictionary이며 이미 import된 모듈과 package들을 저장하고 있다.
즉, 한번 import된 모듈과 package들은 파이썬이 또 다시 찾지 않아도 되도록 하는 기능을 가지고 있다.
파이썬이 모듈이나 package를 찾기위해 가장 먼저 확인하는 곳이다.

sys.path

파이썬이 sys.modules와 built-in-modules를 확인하고 마지막으로 확인하는 곳이다.
경로를 나타내는 string 요소들을 가지고 있는 list구조이다.
파이썬은 경로의 처음부터 끝까지 하나하나 확인하면서 해당 경로에 import하고자 하는 package가 있는지 확인한다.
sys.path에서도 찾지 못하면 ModuleNotFoundError를 리턴한다.


정리

파이썬은 import 하고자 하는 모듈과 package를 찾을때에 먼저 sys.modules를 보고, 없으면 파이썬 built-in-modules를 확인 하고 마지막으로 sys.path에 지정되어 있는 경로들을 확인해서 찾는다.


파이썬이 sys모듈의 위치를 찾는 방법

sys는 파이썬에 포함되어 있는 모듈로서 sys 모듈을 import해서 sys.modules와 sys.path를 출력, 수정할 수 있다.

import sys
print(sys.path)
print(sys.modules)

그렇다면 파이썬은 sys 모듈의 위치를 어떻게 찾을 수 있을까?


sys 모듈은 파이썬에 내장되어 있는 모듈이므로 파이썬은 쉽게 built-in-modules에서 sys를 찾을 수 있다.


absolute path

이름 그대로 절대경로를 뜻하는데 import하는 파일과 경로에 상관없이 항상 경로가 동일하기 때문이다.

└── my_app
    ├── main.py
    ├── package1
    │   ├── module1.py
    │   └── module2.py
    └── package2
        ├── __init__.py
        ├── module3.py
        ├── module4.py
        └── subpackage1
            └── module5.py
from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1.module5 import function2

경로들의 시작점이 전부 최상위 디렉토리에서 시작된다.
따라서 사용자의 현재 위치와 무관하게 경로의 파악을 빠르게 할 수 있다.
일반적으로 local package를 import 할때는 absolute path를 사용하는것을 권장한다.
그러나 디렉토리가 많으면 경로가 길어질 수 있다는 단점이 있다.


relative path

relative path는 absolute path의 단점을 보완하기 위해 이용할 수 있다.

└── my_app
    ├── main.py
    ├── package1
    │   ├── module1.py
    │   └── module2.py
    └── package2
        ├── __init__.py
        ├── module3.py
        ├── module4.py
        └── subpackage1
            └── module5.py
# package2/module3.py
from . import class1
from .subpackage1.module5 import function2

dot . 은 import 가 선언되는 파일의 현재 위치를 말한다. 즉 package2/module3.py의 위치에서 원하는 모듈의 경로를 설정하면 된다.

# subpackage1/module5.py
from ..module4 import class4

dot 2개 .. 를 사용하면 현재위치에서 상위 디렉토리로 가는 경로를 설정할 수 있다.

relative path는 경로의 길이를 줄여줘서 깔끔하게 보일 수 있지만 헷갈리기 쉽고 파일의 위치가 변경되면 경로위치도 변경해줘야 한다.
그러므로 대부분의 경우 absolute path를 사용하는 것을 권장하고 있다.


calculator package


vs code로 실습해보았으며 경로는 다음과 같다.

main.py에서 다음과 같이 상대경로를 설정하고 실행시키면 다음과 같은 에러가 발생한다.

ImportError: attempted relative import with no known parent package의 에러가 발생했는데 대략적인 뜻으로 보아 부모 패키지의 정의가 확실하지 않은 것 같다.
python 공식문서에는 다음과 같이 나와있다.

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.

즉 python에서의 main 모듈(이름뿐만 아니라 실제 main기능을 하도록 프로그래밍된 모듈)은 항상 absolute path로 입력해주어야 한다.


add_and_multiply파일에서 상대경로로 실행해보면 어떻게 될까?
결과는 main파일과 똑같이 ImportError: attempted relative import with no known parent package에러가 발생했다.
calculator는 최상위 디렉토리이기 때문에 앞의 dot을 없애고

from multiplication import multiply

위의 코드처럼 바로 multiplication에 접근하면 구현이 된다.

add_and_multiply파일을 절대경로(위 사진 2line 코드)로 실행하면

다음의 에러가 발생한다.
알고보니 모듈에 의해 import 당하지 않고 파이썬 인터프리터.py로 바로 실행을 하게 될 경우 자기 자신은 main 모듈로 인식하여 다음의 에러가 발생한 것이었다.
main module은 반드시 absolute path로 입력해주어야 하며 calculator는 최상위 패키지이고 포함되어 있으므로 바로 mutiplication에 접근하게 해주면 된다.

from multiplication import multiply

init.py의 역할

init 파일은 해당 디렉토리가 패키지임을 알려주는 역할을 합니다. 즉 파일이 위치한 경로를 패키지 모듈처럼 사용할 수 있도록 해주는 중요한 기능을 수행한다.
그리고 init 파일에 넣고 싶은 패키지와 모듈을 넣는다면 import 패키지 형태로 간단하게 가져올 수 있다.

profile
포기하지 않는 개발자

0개의 댓글