본문 바로가기
C.W.K.
Stream
Lesson 05 of 10 · published

Row Factory — Dict-like access

~10 min · python, row-factory, ergonomics

Level 0Scout
0 XP0/80 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

컬럼을 숫자로 꺼내는 거 그만해

sqlite3는 기본적으로 row를 tuple로 돌려줘. 그래서 컬럼을 숫자로 꺼내게 되는데, 잘 깨지고 읽기도 나쁘고 SELECT 순서만 바뀌어도 무너져. 고치는 데는 한 줄이면 돼.

conn.row_factory = sqlite3.Row

이제 row가 sqlite3.Row가 돼. 인덱스로도 컬럼명으로도 꺼낼 수 있고 순회 순서도 안정적이야. dict은 아니지만 dict(row)로 깔끔하게 바꿀 수 있어. JSON으로 내보낼 때 편하지.

Tip: production 코드에서는 모든 connection에 row_factory = sqlite3.Row를 걸어. 실행 시간에 얹히는 부담은 무시해도 되는 수준이고, 읽기 좋아지는 건 어마어마하고, '컬럼 하나 추가했더니 인덱스가 밀렸다' 부류의 버그가 통째로 사라져.

Code

sqlite3.Row 실전·python
import sqlite3, json

conn = sqlite3.connect('demo.db')
conn.row_factory = sqlite3.Row

row = conn.execute('SELECT id, email, username FROM users LIMIT 1').fetchone()

print(row['email'])              # 'a@x.com' — 이름으로
print(row[1])                    # 'a@x.com' — 인덱스도 됨
print(row.keys())                # ['id', 'email', 'username']

# 진짜 dict 변환 (예: JSON)
print(json.dumps(dict(row)))
Custom row factory — 내 dataclass로 받기·python
import sqlite3
from dataclasses import dataclass

@dataclass
class User:
    id: int
    email: str
    username: str

def user_factory(cursor, row):
    cols = [c[0] for c in cursor.description]
    return User(**dict(zip(cols, row)))

conn = sqlite3.connect('demo.db')
conn.row_factory = user_factory
for user in conn.execute('SELECT id, email, username FROM users'):
    print(user.email)

External links

Exercise

tuple을 돌려주던 query를 하나 골라. connection을 sqlite3.Row로 바꾸고, 부르는 쪽 코드를 컬럼명으로 꺼내도록 고쳐봐. 그다음 dataclass 인스턴스를 돌려주는 custom row factory도 만들어. 각각을 어떤 코드에 쓸지 정해.

Progress

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

댓글 0

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

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