본문 바로가기
프로그래밍

psycopg2에서 데이터를 dictionary 형태로 가져오는 방법

by choihyuunmin 2023. 1. 8.

개요

파이썬에서 postgreSQL 데이터베이스의 데이터를 가져오려면 psycopg2를 이용하여 접근할 수 있다.

기본 사용방법대로 사용하게 되면 데이터가 튜플 타입으로 반환된다.

가져온 데이터를 컬럼:레코드와 같은 key, value 형태의 딕셔너리로 사용하기 위해서는

psycopg2.extras의 RealdictCursor를 사용하면 된다.


실습

간단한 확인을 위해 컬럼이 3개 있는 테이블을 생성하였다.

CREATE TABLE test (
col1 varchar(10),
col2 integer,
col3 timestamp
);

COMMIT;

INSERT INTO test VALUES ('test1', 1, now());
INSERT INTO test VALUES ('test2', 2, now());
INSERT INTO test VALUES ('test3', 3, now());
INSERT INTO test VALUES ('test4', 4, now());
INSERT INTO test VALUES ('test5', 5, now());
INSERT INTO test VALUES ('test6', 6, now());
INSERT INTO test VALUES ('test7', 7, now());

COMMIT;

먼저, 기존 psycopg2 라이브러리의 조회 방식을 사용하여 조회해보면 다음과 같이 튜플 형식으로 반환된다.

import psycopg2

conn_string = {
    "host": "localhost",
    "port": 5432,
    "database": "postgres",
    "user": "postgres",
    "password": "password"
}
conn = psycopg2.connect(**conn_string)
curs = conn.cursor()

sql = "SELECT * FROM test"

curs.execute(sql)
results = curs.fetchall()

for result in results:
    print(result)




>>('test1', 1, datetime.datetime(2023, 1, 8, 21, 13, 48, 873559))
('test2', 2, datetime.datetime(2023, 1, 8, 21, 13, 50, 263238))
('test3', 3, datetime.datetime(2023, 1, 8, 21, 13, 51, 380687))
('test4', 4, datetime.datetime(2023, 1, 8, 21, 13, 52, 39996))
('test5', 5, datetime.datetime(2023, 1, 8, 21, 13, 52, 610510))
('test6', 6, datetime.datetime(2023, 1, 8, 21, 13, 53, 89299))
('test7', 7, datetime.datetime(2023, 1, 8, 21, 13, 53, 631180))

이제 이 데이터를 key, value형식의 딕셔너리로 가져오기 위해서 extras의 RealDictCursor를 기존 connection의 커서에 매핑시켜준다.

import psycopg2.extras

먼저 psycopg2.extras를 import 시켜준뒤,

curs = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

처음 코드에서 커서를 만들어준 부분에, cursor_factory에 위에서 import한 psycopg2.extras의 RealDictCursor 클래스를 매핑시킨다.

sql쿼리를 execute시키고 fetch 하는 부분은 수정 없이 사용해도 된다.

results = curs.fetchall()
print(results)
>>[RealDictRow([('col1', 'test1'), ('col2', 1), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 48, 873559))]), RealDictRow([('col1', 'test2'), ('col2', 2), ('col3', datetime.dateti))]), RealDictRow([('col1', 'test6'), ('col2', 6), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 53, 89299))]), RealDictRow([('col1', 'test7'), ('col2', 7), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 53, 631180))])]

for result in results:
    print(result)
>>RealDictRow([('col1', 'test1'), ('col2', 1), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 48, 873559))])
RealDictRow([('col1', 'test2'), ('col2', 2), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 50, 263238))])
RealDictRow([('col1', 'test4'), ('col2', 4), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 52, 39996))])
RealDictRow([('col1', 'test5'), ('col2', 5), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 52, 610510))])
RealDictRow([('col1', 'test6'), ('col2', 6), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 53, 89299))])
RealDictRow([('col1', 'test7'), ('col2', 7), ('col3', datetime.datetime(2023, 1, 8, 21, 13, 53, 631180))])

커서 변경후 데이터를 조회해보면, RealDictRow라는 객체에 담겨서 반환된다.

ReadDictRow라는 객체를 파이썬에서 사용하는 딕셔너리처럼 이용할 수 있다.

for result in results:
print(result.keys())

>>odict_keys(['col1', 'col2', 'col3'])
odict_keys(['col1', 'col2', 'col3'])
odict_keys(['col1', 'col2', 'col3'])
odict_keys(['col1', 'col2', 'col3'])
odict_keys(['col1', 'col2', 'col3'])
odict_keys(['col1', 'col2', 'col3'])
odict_keys(['col1', 'col2', 'col3'])

for result in results:
print(result.values())

>>odict_values(['test1', 1, datetime.datetime(2023, 1, 8, 21, 13, 48, 873559)])
odict_values(['test3', 3, datetime.datetime(2023, 1, 8, 21, 13, 51, 380687)])
odict_values(['test4', 4, datetime.datetime(2023, 1, 8, 21, 13, 52, 39996)])
odict_values(['test5', 5, datetime.datetime(2023, 1, 8, 21, 13, 52, 610510)])
odict_values(['test6', 6, datetime.datetime(2023, 1, 8, 21, 13, 53, 89299)])
odict_values(['test7', 7, datetime.datetime(2023, 1, 8, 21, 13, 53, 631180)])

for result in results:
print(result["col1"]

>>test1
test2
test3
test4
test5
test6
test7