Python - Module(2)

1.파일 생성

앞서 작성한 TIL에 이어서, 직접 모듈을 absolute path와 relative path로 import해보며 개념을 익혔다.
먼저, 다음과 같이 main파일과 calculator패키지, 각각의 모듈을 생성하였다(__init__파일은 비어있으나 calculator가 패키지임을 알려주는 역할을 함. 최신 버전의 파이썬에서는 필요 없으나 이전 버전과의 compliance를 위해........).

각 파일의 코드는 다음과 같다.

🐍 main.py
<!--absolute path로 import시-->
from calculator.add_and_multiply import add_and_multiply
<!--main.py가 속한 디렉토리(최상단 디렉토리)에서 calculator 폴더의 add_and_multiply에서 add_and_multiply 함수를 찾아 import해라-->


<!--relative path로 import시-->
from .calculator.add_and_multiply import add_and_multiply
<!--main.py가 속한 디렉토리(기준점)의 하위 폴더인 calculator에서 add_and_multiply 모듈의 add_and_multiply 함수를 찾아 import해라-->

if __name__ == '__main__':
    print(add_and_multiply(1,2))
🐍 add_and_multiply.py
<!--absolute path로 import시-->
from calculator.multiplication import multiply
<!--main.py가 속한 디렉토리(최상단 디렉토리)에서 calculator 폴더의 multiplication에서 multiply 함수를 찾아 import해라-->


<!--relative path로 import시-->
from .multiplication import multiply
<!--main.py가 속한 디렉토리(기준점)의 하위 폴더인 calculator에서 multiplication 모듈의 multiply 함수를 찾아 import해라-->


def add_and_multiply(a,b):
    return multiply(a,b) + (a+b)
🐍 multiplication.py
def multiply(a,b):
    return a*b

multiplication.py 파일에 multiply(a,b) 함수가 있고, add_and_multiply.py는 이 함수를 import하여 add_and_multiply(a,b)라는 새로운 함수를 생성하였다. 최종적으로 main.py에서 동 함수를 import하여 사용한다.

2. Relative import 시 에러가 발생하는 문제

add_and_multiply.py 파일의 경우 multiply 함수를 absolute path로 import하든, relative path로 import하든 무리없이 작동한다. 하지만 main.py에서 relative path로 add_and_multiply를 import하여 실행하는 경우 다음과 같은 에러가 발생한다.

ImportError: attempted relative import with no known parent package

(1) __name__ == '__main__'

이 에러의 원인을 파악하기 전에 먼저 아래 코드의 의미부터 알아보자.

if __name__ == '__main__':
    print(add_and_multiply(1,2))

main.py에서 add_and_multiply 함수를 실행하기 전에 '__name__'이 '__main__'일 때만 실행하라는 조건이 붙었다. __name__은 모듈의 이름이 저장되는 변수이다. 만약 모듈이 아닌 직접 실행한 파일의 경우 __name__의 값은 '__main__'이 된다.

하나의 디렉토리 안에 'main.py'와 'module1.py'라는 파이썬 파일 두 개를 만들어서 다음과 같이 작성한 뒤 main.py를 실행시켜보자.

🐍 main.py
import module1

print('Now main\'s __name__ is..', __name__)
🐍 module1.py
print('Module is being printed...')
print('Module\'s __name__ is...', __name__)

터미널에 결과는 다음과 같이 출력된다.

main.py의 모듈인 module1의 결과는 모듈의 이름이지만, main.py의 결과는 __main__이라고 출력되었다.
module1.py에서 실행한다면 다음과 같은 결과가 나온다.

이를 통해 __name__ == '__main__'는 동 파일이 모듈로써가 아닌 그 자체로 실행되는 경우(=스크립트로 실행되는 경우)를 말함을 알 수 있다. 결과적으로

if __name__ == '__main__':
    print(add_and_multiply(1,2))

라고 하면, 동 파일이 모듈로써 import되어 실행되는 경우에는 print를 하지 말라는 의미이다.

(2) 그래서 에러는...?

Relative import를 할 때 파이썬은 모듈의 '__name__'속성을 가지고 모듈의 상대적인 위치를 파악한다. 하지만 __name__ 이 '__main__'인 파일에 대해서는, 파이썬이 위치를 파악하지 못하며 최상단에 위치한 파일로 인식한다. 이렇게 되면 파일의 실제 위치와는 관계 없이 엉뚱한 곳에서 모듈들의 상대적인 위치를 파악하려고 하고, 모듈들을 찾을 수 없게된다.
이러한 이유로 __name__ 이 '__main__'인 main.py에서는 relative import시 오류가 발생하지만 __name__이 모듈의 이름이어서 파일의 위치를 특정하는 것이 가능한 add_and_multiply.py에서는 relative import를 할 수 있다. 따라서 main module에서는 absolute path로 import해야한다.

좋은 웹페이지 즐겨찾기