TIL-python(Modules & Package)

hs·2021년 8월 9일
0

⭐️ sys.modules vs sys.path

  • sys.modules는 파이썬에서 모듈이나 패키지를 찾기 위해 가장 먼저 찾는 곳이며, 디렉토리 형식으로 되어있다.

  • sys.path는 가장 마지막으로 찾아보는 곳이며, list형식에 string요소들을 가지고 있다.

⭐️ sys 모듈의 위치

1
2
3
4
5
import sys
 
print(sys)
 
><module 'sys' (built-in)>
cs
built-in moudules 이라는 것을 알 수 있다. 또한 Linux나 MacOS 인경우 terminal을 통해 python 디렉토리에 들어가

find . -name 'sysmodule.c'

입력을 통해 확인 할 수 있다.

⭐️ Absolute Path & Relative Path

Absolute path

Absolute path는 이름 그대로 절대 경로이다. 파일의 위치에 상관없이 항상 경로가 동일하다. 항상 최상단의 디렉토리를 기준으로 경로를 잡는다.

단점은 경로가 길어질 수 있다는 점

relative path

relative path는 상대경로이다. import하는 위치를 기준으로 경로를 정의한다.
일반적으로 local package안에서 다른 local package를 import할때 사용한다.
. ==> 현재 위치 경로를 나타낸다.
.. ==> 현재 위치의 상위 경로를 나타낸다.

단점은 헷갈리기 쉽고 파일 위치가 변경되면 경로가 전체적으로 바뀐다.

⭐️cacluator 패키지 만들기

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

이런 패키지를 만들었을 때, main.py에서 상대경로로 add_and_mutiply를 import했을 때 발생하는 에러를 확인하고, main module 에서는 패키지의 모듈을 어떻게 임포트 해야하는가?

에러

ImportError: attempted relative import with no known parent package

이 문제를 해결하려면

if __name__ == '__main__

이 부분부터 이해하고 가야된다. 코드 그대로 해석하면 '__name__이라는 변수의 값이 __main__이라면 아래의 코드를 실행하라.' 라는 뜻이다.

파이썬은 C언어나 Java랑은 다르게 main함수가 존재하지 않는다.

🌙 __name__

__name__은 현재 모듈의 이름을 담고 있는 내장변수이다. 이 변수는 직접 실행된 모듈의 경우 __main__이라는 값을 가지게 되고 직접 실행되지않고 import된 모듈은 모듈의 이름(파일명)을 가지게 된다.
예를 하나들어보자.

#module.py

def hello():
	print("Hello")
print(__name__)
#main.py
import module

print(__name__)
module.hello()

module
__main__
Hello

  1. import된 module의 __name__이 먼저 출력
  2. main.py의 __name__이 출력
  3. module의 hello()함수 호출

즉, 직접 실행한 파일은 __name__ 내장변수에 __main__이라는 값이 들어가고 import된 모듈은 각 모듈의 이름이 들어간다는것을 알 수 있다.

다시 문제로 돌아가서 저 한줄로 인해 최상위 모듈이 main.py가 되면서 상대경로로 calculator를 import할 수 없던 것이다. 이를 해결하기 위해선 절대 경로를 이용해 import를 하면 사용가능하다.

⭐️ add_and_multiply.py에서 multiply 호출

상대경로

from .multiplication import multiply
> ImportError: attempted relative import with no known parent package

절대경로

from calculator.multiplication import multiply
> ModuleNotFoundError: No module named 'calculator'

믿었던 절대 경로도 오류라니 무엇이 문제일까?
절대경로를 import할때는 현재의 디렉토리가 sys.path에 포함된다.즉, 같은 디렉토리 내에 존재함으로

from multiplication import multiply

이렇게 실행하면 된다.

⭐️ __init__.py의 역할

__init__.py 파일은 해당 디렉토리가 패키지의 일부임을 알려주는 역할을 한다. 패키지가 포함된 디렉토리에 __init__.py 파일이 없으면 패키지로 인식이 되지않는다.
또한 특정 디렉토리의 모듈을 *을 사용하여 import할 때 해당 디렉토리내의 __init__.py 파일에 __all__변수를 설정하고 import할 수 있는 모듈을 정의해 주어야 한다.

⛔️ 참고

[python]절대경로&상대경로, 상대경로 import 에러 이유와 해결
PEP 328
점프 투 파이썬

profile
무엇이든 끝까지 보람차게

0개의 댓글