[Python]package 와 import

LILO Ghim·2021년 11월 7일
0
post-thumbnail

파이썬이 모듈 또는 package를 찾는 경로

[sys.modules]

파이썬이 모듈이나 패키지를 찾기 위해 가장 먼저 확인 하는 곳
dictionary 구조이며, 이미 import된 모듈과 package들을 저장하고 있다.
한번 import된 모듈과 package들은 다시 찾지 않아도 되도록 하는 기능을 가지고 있다. 따라서 새로 import하는 모듈은 찾을 수 없음

import sys
print(sys.modules)

{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'posix': <module 'posix' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, 'time': <module 'time' (built-in)>, 'zipimport': <module 'zipimport' (frozen)>, '_codecs': <module '_codecs' (built-in)>, 'codecs': <module 'codecs' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/codecs.py'>, 'encodings.aliases': <module 'encodings.aliases' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/encodings/aliases.py'>, 'encodings': <module 'encodings' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/encodings/__init__.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/encodings/utf_8.py'>, '_signal': <module '_signal' (built-in)>, 'encodings.latin_1': <module 'encodings.latin_1' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/encodings/latin_1.py'>, '_abc': <module '_abc' (built-in)>, 'abc': <module 'abc' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/abc.py'>, 'io': <module 'io' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/io.py'>, '__main__': <module '__main__' from '/Users/lilo/Desktop/practice.py'>, '_stat': <module '_stat' (built-in)>, 'stat': <module 'stat' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/stat.py'>, '_collections_abc': <module '_collections_abc' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/_collections_abc.py'>, 'genericpath': <module 'genericpath' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/genericpath.py'>, 'posixpath': <module 'posixpath' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/posixpath.py'>, 'os.path': <module 'posixpath' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/posixpath.py'>, 'os': <module 'os' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/os.py'>, '_sitebuiltins': <module '_sitebuiltins' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/_sitebuiltins.py'>, '_locale': <module '_locale' (built-in)>, '_bootlocale': <module '_bootlocale' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/_bootlocale.py'>, 'site': <module 'site' from '/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site.py'>}

[built-in modules]

이미 파이썬에 포함되어 나오는 모듈

[sys.path]

마지막으로 보는 장소
string 요소들을 가지고 있는 list 구조이다.
*pip로 설치한 외부 모듈도 자동으로 sys.path에 이미 포함되어 있는 site-packages라는 디렉토리에 설치가 된다.

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

-> sys.modules 확인 -> built-in 모듈 확인 -> sys.path 경로 확인 -> ModuleNotFoundError

Local package import

absolute path & relative path

  1. 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 

예를 들어, subpackage1의 module5 모듈의 function2 함수를 import 한다고 했을 때,

(package2.subpackage1.module5.py)

from package2.subpackage1.module5 import function2

-> 동일한 프로젝트 내에서는 어느 파일, 어느 위치에서 import하던지 경로가 항상 동일하다

-> 현재의 프로젝트 디렉토리는 default로 sys.path에 포함되며, 절대경로는 현재의 디렉토리로부터 경로를 시작하게 된다.

""absolute path는 current directory(최상단 디렉토리)로 부터 경로를 시작하게 되는 것 > 일반적으로 local package를 import할 때는 absolute path를 사용하면 됨""


2. relative path

""absolute path가 프로젝트 최상단 디렉토리를 기준으로 경로를 잡는다면, relative path는 import 하는 위치를 기준으로 경로를 정의함""

*local package 안에서 다른 local package를 import 할 때 사용

예를 들어, package2의 module3에서 package2의 class1과 package2의 하위 package인 subpackage1의 module5의 function2 함수를 import 하려고 하면

# package2/module3.py

from . import class1
from .subpackage1.module5 import function2

. -> import가 선언되는 파일의 현재 위치
.. -> 상위 디렉토리로 가는 경로

package 생성 예시


# 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)
   
# add_and_multiply.py

def multiply(a,b):
    return(a*b)
    

-> 위 세 가지 파일로 패키지를 만들고 상대경로로 import를 했을 때, 아래와 같은 에러가 난다

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."

여기서 !!!check!!!

*** if __name__ == "__main__" 은 어떻게 사용되나?

# __name__이라는 변수의 값이 __main__이라면 아래 코드를 실행한다
# 여기서 __name__은 현재 모듈의 이름을 담고 있는 내장 변수이다.
# 즉, 실행되지 않은 import된 모듈은 모듈의 이름(파일명)을 가지게 된다.


if __name__ == '__main__':
    print(add_and_multiply(1,2))
  • 현재 실행하는 main이 되는 파일의 __name__은 __main__이 되는데, 실제 파일의 위치와는 상관없이 최상단 디렉토리인 것처럼 된다.

  • 파이썬 interpreter는 당연히 __main__이라는 모듈의 위치를 알 수 없어서 해당 모듈을 직접 실행한 위치에서부터 절대 위치로 지정해주어야 실행!

    상대 경로는 import하는 위치를 기준으로 경로를 잡는다면 절대경로는 최상단 디렉토리를 기준으로 경로를 잡는다고 했으므로, 현재 실행하고 있는 파일 즉 이름이 __main__파일이라면 자동으로 최상위 파일이 되므로 절대 경로를 넣어주고, import 하는 파일들은 상대 경로이거나 절대경로이어도 무관하다(__name__ = 파일이름).
    만약 import 하는 파일을 실행하며 main이 된다면 당연히 절대 경로로 수정해야 함!

profile
킴릴로

0개의 댓글