-
wecode 과제_ 모듈 및 패키지 관련카테고리 없음 2020. 11. 23. 12:58728x90
sys.modules 와 sys.path의 차이점
- search 순서
sys.module : 모듈 및 패키지가 있는지 확인하는 가장 첫번째 순서
sys.path : 가장 마지막 확인 순서
- 자료구조의 형태
sys.module : 단순한 디렉토리(directory) 형태로 {"sys" : <module 'sys' (built-in)> } 형택의 딕서녀리형의 자료구조
sys.path : string 요소들을 가지고 있는 ['/Users/munseunghui/playground/wecode_python/Module만들기', ]
형태의 리스트형 자료구조
- 역할적 측면
sys.module : 한번 import 된 모듈, 패키지를 저장하고 있어, 파이썬이 다시 찾기 않아도 되도록 하는 기능을 가짐
새로 import하는 모듈은 sys.module에서 찾을 수 없다(이미 한번 import 한 모듈과 패키지가 들어있기 때문)
sys.path : pip 명령어로 받은 파일은 site-packages에 저장되는데, site-packages는 sys.path에 포함되어 있어
pip 로 설치한 모듈, 패키지를 쉽게 찾을 수 있게 도와준다(?).
sys 도 import 해야하는 모듈이다, 파이썬은 sys 모듈의 위치를 어떻게 찾을 수 있을까?
sys (System-specific parameters and functions)
sys는 파이썬에서 제공하는 모듈이다. os모듈안에 있으며 파이썬 인터프리터가 제공하는 변수와 함수를
직접 제어할 수 있게 해주는 모듈이다. C언어로 작성되어 있다.
sys 모듈의 위치 확인하기
sys.modules 를 출력해보면 확인할 수 있다.
import sys print(sys.modules) # {'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins'....}
Absolute path와 relative path의 차이점
- 경로의 기준
절대 경로 : 해당 프로젝트의 최상위 디렉토리를 기준으로 함
경로의 시작점은 current directory로 해당 프로젝트 내부의 어느 파일에서든지 절대 경로로 접근이 가능
( current directory 라는 현재의 프로젝트 디렉토리는 Default로 sys.path에 포함되게 된다.)
상대 경로 : Import 하는 위치를 기준으로 함
import 하는 위치를 기준으로 하기에 프로젝트 내부의 어느 파일에서 접근하는지에 따라 경로가 바뀐다.
- 경로 충돌이 일어 날 경우 원인 파악의 정도
절대 경로 : 모듈 및 패키지의 시작, 끝 경로가 명확하기에 모듈, 패키지의 위치를 찾아가기 수월함
상대 경로 : 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)
multiplication.py
def multiply(a,b): return(a*b)
위의 상황에서 아래 문제들을 풀어보자
1. main.py 에서는 절대 경로와 상대 경로를 모두 표기해두었다.
여기서 절대 경로로는 error 가 발생하지 않지만 상대 경로에서는 error가 발생하는 이유를 알아보자.
# absoulte path #from calculator.add_and_multiply import add_and_multiply # 정상동작 # relative path from .calculator.add_and_multiply import add_and_multiply #error if __name__ == '__main__': print(add_and_multiply(1,2))
Traceback (most recent call last): File "/Users/munseunghui/playground/wecode_python/calculator패키지/main.py", line 5, in <module> from .calculator.add_and_multiply import add_and_multiply ImportError: attempted relative import with no known parent package
출처 :velog.io/@ifyouseeksoomi/Backend-Python-Modules-adlpcvz4
상대 경로를 입력시 import error가 발생하는 것을 볼 수 있다.
상대 경로를 통한 import는 import하는 현재 위치를 기준으로 한다.
파이썬에서는 main module 이름은 실제로, 언제나 'main'이기에 메인 모듈로 가능하도록 프로그래밍된 모듈들은
언제나 절대 경로를 입력해줘야한다.
(어떤 프로젝트의 main module은 항상 절대 경로를 입력해줘야한다.)
따라서 절대 경로로 import 해주면 정상동작하는 것을 볼 수 있다.
# absoulte path from calculator.add_and_multiply import add_and_multiply if __name__ == '__main__': print(add_and_multiply(1,2)) # 5
아래의 코드는 왜 사용할까?
if __name__ == '__main__':
이 코드는 현재 스크립트 파일이 실행되는 상태를 파악하기 위해 사용한다.
파이썬은 최초로 시작하는 스크립트 파일과 모듈의 차이가 없습니다. 어떤 스크립트 파일이든 시작점도 될 수 있고, 모듈도 될 수 있습니다. 그래서 __name__ 변수를 통해 현재 스크립트 파일이 시작점인지 모듈인지 판단합니다.
if __name__ == '__main__':처럼 __name__ 변수의 값이 '__main__'인지 확인하는 코드는 현재 스크립트 파일이 프로그램의 시작점이 맞는지 판단하는 작업입니다. 즉, 스크립트 파일이 메인 프로그램으로 사용될 때와 모듈로 사용될 때를 구분하기 위한 용도입니다.
__name__ 은 모듈의 이름이 저장되는 변수이며 import로 모듈을 가져왔을때 모듈의 이름이 들어가게 된다.
하지만 파이썬 인터프리터로 스크립트 파일을 직접 실행했을때는 모듈의 이름이 아니라 "__main__"이 들어가게 된다.
main.py라는 파일은 스크립트 파일 그대로 실행하거나, 자체를 main 모듈로 불러와 실행하게 된다.
스크립트 파일을 모듈로 사용할때는 어떠한 변수/함수 만 사용하는 것이 목적이기에 모듈로 불러와 실행할때는
원하고자 하는 변수/함수 만 사용가능하게끔 환경을 구성해준다.
파이썬은 왜 프로그램의 시작점이 정해져 있지 않나요?
파이썬이 처음에 개발 될 당시에는 리눅스/유닉스에서 사용하는 스크립트 언어 기반이었기 때문에 프로그램의 시작점이 따로 정해져 있지 않았습니다. 보통 리눅스/유닉스의 스크립트 파일은 파일 한 개로 이루어진 경우가 많은데, 이 스크립트 파일 자체가 하나의 프로그램이다 보니 시작점이 따로 필요하지 않습니다. 하지만 C 언어나 자바같은 언어는 처음 만들어질 때부터 소스 파일을 여러 개 사용했기 때문에 여러 소스 파일의 함수들 중에서도 시작 함수(main)를 따로 정해 놓았습니다.
add_and_multiply.py에서 multiply함수를 절대경로와 상대경로로
각각 import 해보고 main 모듈과 차이점을 생각해보고 결과를 출력해보자
절대 경로
\User\munseunghui\playground\wecode_python\calculator패키지\
# add_and_multiply.py from calculator.multiplication import multiply def add_and_multiply(a,b): return multiply(a,b) + (a+b)
Traceback (most recent call last): File "/Users/munseunghui/playground/wecode_python/calculator패키지/calculator/add_and_multiply.py", line 2, in <module> from calculator.multiplication import multiply ModuleNotFoundError: No module named 'calculator'
모듈에 의해 import 당하지 않고 파이썬 인터프리터.py로 바로 실행을 하게 될 경우
자기 자신은 main 모듈로 인식하는 것을 알 수 있다.
파이썬에서는 main 모듈의 경우 상대 경로가 아닌 반드시 절대 경로로 입력해야 에러가 발생하지않는다.
따라서 상대 겨오로 적었을 경우에는 에러가 발생하고
최상단 패키지 calculator에 포함되어있으므로 바로 multiplication 에 모듈로 접근하며 된다.
# add_and_multiply.py from multiplication import multiply def add_and_multiply(a,b): return multiply(a,b) + (a+b) print(add_and_multiply(10,20)) print("name of add_and_multiply.py: ", __name__) # 230 name of add_and_multiply.py: __main__
상대 경로
\User\munseunghui\playground\wecode_python\calculator패키지\
from .multiplication import multiply def add_and_multiply(a,b): return multiply(a,b) + (a+b)
Traceback (most recent call last): File "/Users/munseunghui/playground/wecode_python/calculator패키지/calculator/add_and_multiply.py", line 1, in <module> from .multiplication import multiply ImportError: attempted relative import with no known parent package
상대경로에서 (.) 점 삭제 == 여기서 점은 import가 선언되는 add_and_multiply.py를 뜻하며
최상단 패키지 calculator에 포함되어있으므로 바로 multiplication 에 모듈로 접근하며 된다.
from multiplication import multiply def add_and_multiply(a,b): return multiply(a,b) + (a+b) print(add_and_multiply(10,20)) # 230
실제 main 모듈은 main.py로 이나
파이썬 인터프리터.py로 단독으로 실행하면 해당 .py 는 자기 자신은 main으로 인식하게 된다.
main 모듈이 아님에도 불구하고 단독 실행시 자기자신은 main으로 인식하여 위의 문제와 마찬가지로
main 모듈에 상대 경로 import를 사용할 수 없는 환경이기 때문에 에러가 발생하는것으로 보인다.
__init__.py 파일의 역할
__init__.py는 자신이 위치한 디렉토리가 패키지의 일부임을 확인해주는 역할을 한다.
python의 버전 3.3부터는 __init__.py 파일이 없어도 패키지를 인식하도록 업데이트되었다고 한다.
하지만 하위 호환을 위해 __init__.py를 생성하는 것이 안전하다.
728x90