KeyError와 IndexError가 났을 때 get이나 try 중 무엇을 쓸지 정하는 기준
문제 발생
응답 데이터를 다루는 코드에서 두 예외가 번갈아 났습니다.
user["nickname"] # KeyError: 'nickname'
items[3] # IndexError: list index out of range급한 대로 전부 try/except로 감쌌더니, 정작 진짜 버그도 함께 조용히 넘어가게 됐습니다.
원인 분석
파이썬 문서의 정의는 짧고 명확합니다.
KeyError— "매핑(딕셔너리)의 키가 기존 키 집합에서 발견되지 않을 때" 발생합니다.IndexError— "시퀀스 첨자가 범위를 벗어났을 때" 발생합니다.
둘 다 LookupError의 하위 클래스라 함께 잡을 수 있습니다.
IndexError에는 알아 둘 만한 단서가 있습니다 — 슬라이스 인덱스는 허용 범위로 조용히 잘리고, 인덱스가 정수가 아니면 IndexError가 아니라 TypeError가 납니다.
items = [1, 2]
items[5] # IndexError
items[2:99] # [] — 예외 없이 빈 리스트핵심은 예외를 없애는 방법이 아니라 "없는 것이 정상인가"를 먼저 정하는 것입니다. 정상이면 기본값으로 흘려보내고, 비정상이면 예외가 나는 편이 낫습니다 — 조용히 넘기면 잘못된 데이터가 그대로 아래로 흘러갑니다.
해결 방안
- 없어도 되는 값은
get으로 기본값을 줍니다.
nickname = user.get("nickname", "익명")- 여러 단계라면 중간이 없을 때를 함께 처리합니다.
city = (payload.get("address") or {}).get("city")- 키마다 기본값을 자동으로 만들려면
defaultdict나setdefault를 씁니다. 누적 집계에서 특히 편합니다.
from collections import defaultdict
counts = defaultdict(int)
for tag in tags:
counts[tag] += 1 # 없던 키도 0에서 시작- 있어야 하는데 없다면 예외를 살립니다. 대신 어떤 키였는지 맥락을 붙여 다시 던집니다.
try:
user_id = payload["id"]
except KeyError as error:
raise ValueError(f"응답에 id가 없습니다: {payload}") from error- 시퀀스는 길이를 먼저 확인하거나 슬라이스를 씁니다. 슬라이스는 범위를 넘어도 예외가 나지 않으므로 "앞의 N개"류 처리에 적합합니다.
first_three = items[:3] # 개수가 부족해도 안전except Exception으로 뭉뚱그리지 않습니다.KeyError를 잡으려다TypeError까지 삼키면 원인을 못 찾습니다. 잡을 예외를 좁게 지정합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.