C.W.K.
Stream
Lesson 01 of 05 · published

import — Python 이 코드 찾고 로드하는 법

~22 min · import, module, sys.path, package

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

import 가 진짜 하는 일

import json 쓰면 Python 이 sys.path 의 디렉토리들을 순서대로 검색, json 이름의 파일/디렉토리 찾고, 본문 한 번 실행 (결과 sys.modules 에 캐시), 네임스페이스에 json 이름 바인딩. 이후 import json 호출은 dict lookup 일 뿐 — 본문 안 다시 실행.

4 import 형태

import x — 이름 x 바인딩. import x.yx 바인딩, x.y 로 접근. from x import yy 바인딩 (x 로드되지만 바인딩 X). from x import y as zz 바인딩. from 형태가 y 를 sub-module 또는 x 의 속성으로 찾음.

절대 vs 상대 import

절대 import 는 전체 path — from mypackage.subpkg import mod. 상대 import 는 점 사용 — from . import sibling (같은 패키지), from .. import parent_sibling (부모 sibling). 현대 Python 스타일 — 절대 import 선호, 패키지 ship 하면서 안에서 import 할 때만 상대 (rename 시 깨지는 문제 회피).

from x import * 함정

from x import *x 가 노출하는 모든 거 import (__all__ 또는 fallback 으로 public 이름). 네임스페이스 오염 + "이 이름 어디서 왔지?" 답하기 어렵게. REPL 편의와 빡빡 scope 의 wildcard re-export 드문 경우에 예약.

원칙: Import 는 문. 부작용 (import 된 모듈 실행) 있어. 모든 import 를 파일 상단에 두면 부작용이 예측 가능. 함수 안 숨겨진 import 는 특정 이유 (순환 import 회피, 비싼 로드 지연) 없으면 코드 냄새.

Code

4 형태 — 각각 뭐 바인딩·python
# 형태 1 — 모듈 바인딩
import json
print(json.dumps({"a": 1}))

# 형태 2 — top-level 패키지 바인딩, 점으로 submodule 접근
import os.path
print(os.path.join("a", "b"))     # 'os' 가 바인딩

# 형태 3 — 모듈에서 이름 바인딩
from datetime import datetime
print(datetime.now())

# 형태 4 — import 시 rename
import numpy as np                # 매우 흔한 alias
import pandas as pd
Python 이 모듈 찾는 법 — sys.path·python
import sys
for p in sys.path:
    print(p)
# 일반 내용:
# 1. 스크립트 디렉토리 (또는 인터랙티브면 '')
# 2. PYTHONPATH 환경변수의 디렉토리
# 3. 표준 라이브러리 디렉토리
# 4. site-packages

# 로드된 모듈 위치 확인
import json
print(json.__file__)               # /path/to/lib/python3.x/json/__init__.py
캐시된 import — 본문 한 번 실행·python
# /tmp/loud.py
# print("loud 모듈 로딩")
# value = 42

import sys
sys.path.insert(0, "/tmp")

import loud                       # 'loud 모듈 로딩' 한 번 출력
import loud                       # 아무것도 — sys.modules 에 이미 캐시
print(loud.value)                 # 42

# 강제 reload
import importlib
importlib.reload(loud)            # 'loud 모듈 로딩' 다시 출력
상대 import — 패키지 안에서·python
# 이런 패키지 구조 가정:
# mypackage/
#   __init__.py
#   core.py
#   utils.py
#   sub/
#     __init__.py
#     helper.py

# mypackage/utils.py 안
# from .core import important_thing       # 같은 레벨 — 같은 패키지
# from . import core                       # 같은 레벨 — 모듈 참조

# mypackage/sub/helper.py 안
# from ..core import important_thing       # 한 레벨 위
# from .. import utils                     # 부모 sibling

# 상대 import 는 패키지 안에서만 — top-level 모듈은 못 씀.

External links

Exercise

디렉토리 /tmp/quest_pkg/ + __init__.py (빈), 세 모듈 — a.py (x = 1 정의), b.py (from .a import x + x*2 출력), c.py (from quest_pkg.a import x). /tmpsys.path 에 추가 + 각각 import. b 의 상대 import 와 c 의 절대가 같은 결과 확인.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.