Package, module, import에 대해

JM·2020년 5월 30일
0

Python

목록 보기
3/5

Import Search 순서

  1. sys.modules
  2. built-in modules
  3. sys.path

순으로 찾습니다.

sys.modules

  • 파이썬이 모듈이나 package를 찾기위해 가장 먼저 확인하는 곳입니다.
  • sys.modules는 단순한 dictionary 입니다. 그리고 이미 import된 모듈과 package들을 저장하고 있습니다.
  • 한번 import된 모듈과 package들은 파이썬이 또 다시 찾지 않아도 되도록 하는 기능을 가지고 있습니다.
  • 새로 import 하는 모듈은 sys.modules 에서 찾을 수 없습니다.

built-in modules

  • 파이썬에서 제공하는 파이썬 공식 라이브러리들 입니다.
  • Built-in 모듈들은 이미 파이썬에 포함되어 나오므로 파이썬이 쉽게 찾을 수 있습니다.

sys.path

  • 마지막으로 보는 장소가 바로 sys.path 입니다.
  • sys.path는 기본적으로 list이며 string 요소들을 가지고 있는 list 입니다.

파이썬은 list의 각 경로를 하나 하나 확인하면서 해당 경로에 import 하고자 하는 package가 위치해 있는지 확인합니다.

참고로 sys 는 파이썬에 포함되어 있는 모듈입니다. 그러므로 다음 처럼 sys 모듈을 import 해서 sys.modules와 sys.path 를 출력할수도 있고 수정 할 수 도 있습니다.

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

Absolute path와 relative path

Absolute path

  • 이름 그대로 절대 경로 입니다. 왜 절대 경로인가 하니, import를 하는 파일이나 경로에 상관없이 항상 경로가 동일하기 때문입니다.
  • 일반적으로 local package를 import 할때는 absolute path를 사용하면 됩니다.

relative path

  • absolute path를 사용하게 되면 한가지 단점이 있는데 바로 경로가 길어질 수 있다는 점이 있는데, 이러한 단점을 보완하기 위해서 relative path를 사용할 수 있습니다.
  • Relative path 는 absolute path와 다르게 프로젝트의 최상단 디렉토리를 기준으로 경로를 잡는게 아니라 import 하는 위치를 기준으로 경로를 정의합니다. 그래서 일반적으로 relative path는 local package 안에서 다른 local package를 import 할때 사용됩니다

각자 방법에는 장,단점이 있습니다. Relative path는 선언해야 하는 경로의 길이를 줄여준다는 장점은 있지만 헷갈리기 쉽고 파일 위치가 변경되면 경로 위치도 변경되어야 하는 단점이 있습니다. 그러므로 웬만한 경우 absolute path를 사용하는게 권장 됩니다.

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))

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)

이렇게 패키지와 모듈을 구성하고 실행을 해보면

Traceback (most recent call last):
File "C:\Users\준모\AppData\Local\Programs\Python\Python38-32\Project\main.py", line 5, in
from .calculator.add_and_multiply import add_and_multiply
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.

main_module에서 다시 절대적 경로로 변경하여 실행을 해보면

main.py

#absoulte path
from Project.calculator.add_and_multiply import add_and_multiply
if name == 'main':
print(add_and_multiply(1,2))

= RESTART: C:\Users\준모\AppData\Local\Programs\Python\Python38-32\Project\main.py
5
결과가 잘 나옵니다.

main_module이 아닌 다른 module에서 import

이번엔 main.py이 아닌 add_and_multiply.py에서 multiply함수를 절대경로와 상대경로도 import 해보겠습니다.

add_and_multiply.py(절대적 경로)

from Project.calculator.multiplication import multiply
#from calculator.multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)

제대로 작동이 됩니다. 그럼 이번엔

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)

Traceback (most recent call last):
File "C:\Users\준모\AppData\Local\Programs\Python\Python38-32\Project\calculator\add_and_multiply.py", line 1, in
from .multiplication import multiply
ImportError: attempted relative import with no known parent package

이러한 에러를 볼 수 있는데, 이는 위에서 말한대로 상대적 경로는 프로젝트의 최상단 디렉토리를 기준으로 경로를 잡는게 아니라 import 하는 위치를 기준으로 경로를 정의하기 때문에 해당 코드를 이렇게 바꿔줍니다.

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)

제대로 작동하는 모습을 볼 수 있습니다.

init.py의 역할

  • 해당 디렉터리가 패키지의 일부임을 알려주는 역할을 합니다.
  • 디렉터리내에 init.py가 없다면 패키지로 인식하지 않습니다.
  • init.py 파일 안에는 해당 디렉터리에서 공통으로 적용 가능한 기능이나 모듈을 포함할 수 있습니다.

all

  • 패키지 안에서 'import ' 로 사용하고 싶다면 init.py 파일 안의 all 변수에 로 선언할 때 호출할 모듈들을 선언해줘야 합니다.

  • 선언 방법은 all = ['포함될 모듈 네임', '포함될 모듈 네임', '포함된 모듈 네임', ...]

0개의 댓글