모듈과 import는 문법 자체보다 이름 공간을 어떻게 나누고, import 시 어떤 코드가 실행되게 둘 것인가를 먼저 보면 판단이 빨라집니다.
출처를 드러낼지, 짧게 가져올지, import 시 부작용을 줄일지에 따라 import module, from module import name, main guard 사용이 갈립니다.
핵심 정리
import math
from pathlib import Path
root = Path("data")
area = math.pi * 3 ** 2문법
기본 형태는 모듈 단위 import, 이름 import, 패키지에서 모듈 import 세 가지로 보면 됩니다.
import module
from module import name
from package import module모듈 구조
모듈은 코드를 파일 단위 이름 공간으로 나눈다
Python에서 .py 파일 하나가 곧 모듈입니다. 모듈을 나누는 가장 큰 이유는 코드 재사용도 있지만, 이름 충돌을 줄이고 책임을 분리하는 것에 있습니다.
# utils.py
def normalize_name(name: str) -> str:
return name.strip().title()이렇게 파일을 나누면 함수가 어디에 속하는지와 무엇이 공개 API인지 훨씬 분명해집니다.
import 선택
import 방식은 가독성과 충돌 위험의 균형 문제다
import module은 출처를 분명히 보여 주고, from module import name은 짧게 쓸 수 있습니다.
import math
print(math.sqrt(16))
from pathlib import Path
print(Path("."))짧은 이름이 자주 쓰이는 경우를 빼면, 큰 모듈은 보통 import module이 더 읽기 쉽습니다.
실행 분리
import 시 실행 부작용을 줄여야 모듈이 재사용 가능해진다
모듈은 import되는 순간 top-level 코드가 실행됩니다. 따라서 테스트나 재사용을 생각하면, 실행 로직은 함수나 main guard 안으로 넣는 편이 좋습니다.
# 좋지 않은 예: import할 때 바로 실행
print("module loaded")
# 더 좋은 예
def main():
print("run")모듈 정의와 실행 흐름을 분리해 두면 예측 가능한 코드가 됩니다.
def main():
print("run")
if __name__ == "__main__":
main()즉 import되는 모듈은 "정의", 직접 실행되는 파일은 "entry point"를 가진다고 나눠 보면 흐름이 명확합니다.
구조 선택
import를 볼 때 어떤 기준을 보나
| 상황 | 적합한 선택 |
|---|---|
| 모듈 출처를 명확히 보임 | import module |
| 짧은 이름을 자주 사용 | from module import name |
| 여러 유틸을 구조적으로 분리 | 모듈/패키지 분할 |
| import 시 부작용 최소화 | top-level 실행 코드 줄이기 |
| 실행용 스크립트 분기 | if __name__ == "__main__": |
주의할 점
from module import *는 이름 출처를 흐리게 하고 충돌을 만들기 쉽습니다.
# ❌ 어디서 들어온 이름인지 읽기 어렵다
from math import *
print(sqrt(16))
# ✅ 출처를 드러내거나 필요한 것만 명시적으로 가져오기
import math
print(math.sqrt(16))
from math import sqrt
print(sqrt(16))
# ❌ import만 했는데 메시지가 찍히면 재사용성이 떨어진다
print("module loaded")
# ✅ 실행 코드는 main guard 안으로 보낸다
if __name__ == "__main__":
print("module loaded")참고 링크
2 sources