Python3로 개발을 하다 보면 패키지 내의 모듈을 바로 실행하고 싶은 욕망에 빠져듭니다. Main 진입점이 있는 여타 언어와 달리 python 파일 자체가 스크립트처럼 사용할 수 있어서 그럴 것입니다. 그러나 막상 만나는 건 Import Error. 그리고 허둥지둥 구글링을 해보죠. m 옵션을 주고 경로 대신 패키지 형식을 입력하여 실행하면 된다고 합니다. python3 -m foo.bar.baz로 해보니 실행이 됩니다. m 옵션이 어떤 역할을 하기에 가능할까요?
아래는 예시 입니다.
1 | project_root/ |
1 | from foo import qux |
1 | print("Qux Imported.") |
1 | pwd |
Import
m 옵션에 대해 설명을 하기 전에 Python3의 Import에 대해서 알아봐야 합니다. 크게 두 가지 방식이 있습니다.
절대 경로 임포트(Absolute Import)
먼저 절대 경로 임포트 입니다. 라이브러리를 활용할떄 일반적으로 사용하는 Import 문법으로 보시면 됩니다.1
2import requests
from foo import bar
절대 경로 임포트 시 패키지를 sys.path에서 찾습니다. sys.path에 프로젝트의 Root Path가 없는 경우가 위에서 흔히 일어나는 Import Error 상황입니다.
패키지 내 모듈을 바로 실행하면 해당 모듈의 패키지가 sys.path에 들어가기 때문입니다.
명시적 상대 경로 임포트(Explicit Relative Import)
다음은 명시적 상대 경로 임포트 입니다.1
2from .foo import bar
from ..foo import bar
명시적 상대 경로 임포트 시 패키지를 현재 실행 중인 모듈의 __package__와 __name__값을 기준으로 찾습니다. 이때 __package__가 우선순위를 가집니다.
패키지 내 모듈을 바로 실행하면 __package__값은 None이고 __name__은 __main__이 되기 때문에 명시적 상대 경로의 기준이 없어 Import Error가 나타납니다.
암묵적 상대 경로 임포트(Implicit Relative Import)
Python2에는 있었으나 Python3부터 사라진 기능입니다. 따로 내용을 넣진 않겠습니다만 궁금하시면 찾아보셔도 좋습니다.
m option
m 옵션은 모듈을 스크립트처럼 활용할 수 있게 해주는 옵션입니다. 이 말이 무슨 말이냐 하면 python3 -m foo.bar.baz로 실행 시 sys.path엔 ‘’가 들어가고 __package__값은 foo.bar가 됩니다.
프로젝트의 Root Path에서 m 옵션을 활용한다고 했을 때 sys.path에 ‘’가 들어가므로 절대 경로 임포트가 가능하며 __package__값도 foo.bar가 되어 명시적 상대 경로 임포트도 가능해집니다.
결론
m 옵션이 만능열쇠처럼 쓰여 있지만 테스트 목적 외에 사용하지 않는 게 좋습니다. 모듈을 항상 스크립트처럼 쓰고 싶은 건 아닐 테니까요. 그리고 사실 테스트를 위해서도 unit test가 더 적합해 보입니다.
Author: dbgsprw
Link: https://dbgsprw.github.io/2019/02/07/Python3-Import/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.