Sửa lỗi Python KeyError: 'key_name' Khi Truy Cập Dictionary

beginner🐍 Python2026-03-18| Python 2.7+, Python 3.x — tất cả hệ điều hành (Linux, macOS, Windows)

Error Message

KeyError: 'key_name'
#python#keyerror#dictionary

Lỗi Này Là Gì

Chương trình của bạn bị crash giữa chừng với một dòng thông báo trông có vẻ đơn giản:

KeyError: 'key_name'

Traceback đầy đủ:

Traceback (most recent call last):
  File "app.py", line 5, in <module>
    value = data['username']
KeyError: 'username'

Nghĩa là: bạn đang yêu cầu Python lấy một key không tồn tại trong dictionary. Python không tự đoán — nó chỉ crash thẳng.

Nguyên Nhân

Cú pháp dấu ngoặc vuông (dict['key']) rất nghiêm ngặt. Nếu key không tồn tại, Python ném ra KeyError ngay lập tức — không có giá trị dự phòng, không có cảnh báo. Các nguyên nhân thường gặp:

  • Gõ nhầm tên key — 'Username' so với 'username' (Python phân biệt chữ hoa chữ thường)
  • Key chưa bao giờ được thêm vào dictionary
  • Response từ API hoặc JSON đôi khi thiếu trường đó
  • Key đã bị xóa ở đâu đó trước trong code
  • Duyệt qua dữ liệu có cấu trúc không đồng nhất, không phải item nào cũng có cùng các key

Cách Sửa Từng Bước

Bước 1 — In dictionary ra trước

Đừng đoán mò. Hãy in dictionary ra và xem chính xác nó chứa gì:

data = {'user': 'alice', 'age': 30}
print(data.keys())  # dict_keys(['user', 'age'])
print(data)         # {'user': 'alice', 'age': 30}

Chín trong mười trường hợp, cách này lộ ra nguyên nhân ngay — 'username' so với 'user', hoặc sự khác biệt về chữ hoa chữ thường ngoài mong đợi.

Bước 2 — Chuyển sang .get() để truy cập an toàn

.get(key, default) là cách sửa đơn giản nhất. Nó trả về None (hoặc giá trị mặc định bạn chỉ định) thay vì crash:

# Trước — crash nếu key không tồn tại
value = data['username']

# Sau — an toàn
value = data.get('username')          # trả về None nếu không có key
value = data.get('username', 'guest') # trả về 'guest' nếu không có key

Chỉ một thay đổi này loại bỏ được hầu hết các lỗi KeyError khi xử lý response từ API.

Bước 3 — Dùng in để kiểm tra trước khi truy cập

Cần xử lý logic khác nhau tùy theo key có tồn tại hay không? Toán tử in giải quyết điều đó gọn gàng:

if 'username' in data:
    value = data['username']
    print(f"Xin chào, {value}")
else:
    print("Không tìm thấy username trong data")

Bước 4 — setdefault() đọc và lưu giá trị dự phòng trong một bước

Hữu ích khi bạn muốn đọc một key và đồng thời lưu giá trị mặc định vào dictionary nếu key đó chưa có:

data = {}
value = data.setdefault('count', 0)  # thêm 'count': 0 vào dict và trả về 0
print(data)  # {'count': 0}

Bước 5 — defaultdict cho dictionary có nhiều key bị thiếu

Đang xây dựng tổng hợp dữ liệu hay bộ đếm? collections.defaultdict tự động tạo các key bị thiếu ngay lần đầu truy cập, nên lỗi không bao giờ xảy ra:

from collections import defaultdict

counts = defaultdict(int)  # các key thiếu mặc định là 0
words = ['apple', 'banana', 'apple', 'cherry']

for word in words:
    counts[word] += 1  # không có KeyError, tự bắt đầu từ 0

print(dict(counts))  # {'apple': 2, 'banana': 1, 'cherry': 1}

Bước 6 — Dictionary lồng nhau cần chuỗi .get()

Truy cập ba cấp sâu trong một JSON response? Chỉ cần một cấp bị thiếu là toàn bộ chuỗi ném ra KeyError. Hãy sửa bằng cách nối chuỗi các lời gọi .get() với giá trị dự phòng là dict rỗng:

response = {
    'user': {
        'profile': {
            'email': 'alice@example.com'
        }
    }
}

# Rủi ro — bất kỳ cấp nào bị thiếu đều gây KeyError
email = response['user']['profile']['email']

# An toàn — trả về None nếu bất kỳ cấp nào không tồn tại
email = response.get('user', {}).get('profile', {}).get('email')
print(email)  # 'alice@example.com' hoặc None

Kiểm Tra Sau Khi Sửa

Chạy lại code. Không còn traceback nghĩa là đã sửa thành công. Một bài kiểm tra nhanh bao phủ cả ba tình huống:

data = {'name': 'Bob'}

print(data.get('name'))              # Bob
print(data.get('email', 'not set'))  # not set
print(data.get('age'))               # None  (không crash)

Tóm Tắt Nhanh

  • dict['key'] — crash nếu key không tồn tại (chỉ dùng khi chắc chắn key luôn có)
  • dict.get('key') — trả về None một cách an toàn
  • dict.get('key', default) — trả về giá trị dự phòng bạn chỉ định
  • 'key' in dict — kiểm tra sự tồn tại trước khi truy cập
  • dict.setdefault('key', default) — đọc và chèn giá trị mặc định trong một bước
  • defaultdict(type) — tự động tạo key bị thiếu khi truy cập

Lưu Ý

  • Response từ API và dữ liệu JSON không thể đoán trước — luôn dùng .get(). Những trường tồn tại trong 99% response sẽ có lúc bị thiếu trong 1% còn lại.
  • KeyError bên trong vòng lặp thường có nghĩa là một item có cấu trúc khác. Hãy in từng item ra để tìm cái bất thường.
  • Với dictionary config mà key bị thiếu là lỗi thực sự, hãy giữ nguyên dict['key']. Dùng .get() tràn lan sẽ âm thầm bỏ qua các vấn đề nghiêm trọng.
  • Từ Python 3.8 trở lên, TypedDictpydantic có thể ràng buộc cấu trúc dictionary ở tầng kiểu dữ liệu — giải pháp tốt hơn về lâu dài cho các codebase lớn với cấu trúc dữ liệu phức tạp.

Related Error Notes