Шаг 202.
Основы языка Python.
Доступ к базе данных SQLite из Python. Обработка результата запроса (окончание)

    На этом шаге мы рассмотрим некоторые атрибуты, позволяющие изменить отображение результатов запроса.

    Все рассмотренные методы возвращают запись в виде кортежа. Если необходимо изменить такое поведение и, например, получить записи в виде словаря, то следует воспользоваться атрибутом row_factorу объекта соединения. В качестве значения атрибут принимает ссылку на функцию обратного вызова, имеющую следующий формат:

def <Название функции>(<Объект-курсор>, <Запись>):
    #  Обработка записи 
    return <Новый объект>

    Для примера выведем записи из таблицы user в виде словаря:

# -*- coding: utf-8 -*-
import sqlite3
def my_factory (c, r):
    d = {}
    for i, name in enumerate (c.description):
        d[name[0]] = r[i] # Ключи в виде названий полей
        d[i] = r[i]       # Ключи в виде индексов полей
    return d

con = sqlite3.connect("catalog.db")
con.row_factory = my_factory
cur = con.cursor()        # Создаем объект-курсор
cur.execute("SELECT * FROM user")
arr = cur.fetchall()
print(arr)                # Результат
print(arr[0][1])          # Доступ по индексу
print(arr[0]["email"])    # Доступ по названию поля
cur.close ()              # Закрываем объект-курсор
con.close ()              # Закрываем соединение
input ()
Архив с файлом можно взять здесь.

    Результат работы приложения:

[{0: 1, 1: 'unicross@mail.ru', 2: 'password1', 'passw': 'password1', 'email': 'unicross@mail.ru', 'id_user': 1}] unicross@mail.ru unicross@mail.ru

    Функция my_factory() будет вызываться для каждой записи. Обратите внимание на то, что название функции в операции присваивания атрибуту row_factory указывается без круглых скобок. Если скобки указать, то смысл операции будет совсем иным.

    Атрибуту row_factory можно присвоить ссылку на объект Row из модуля sqlite3. Этот объект позволяет получить доступ к значению поля как по индексу, так и по названию поля, причем название не зависит от регистра символов. Объект Row поддерживает итерации, доступ по индексу и метод keys(), который возвращает список с названиями полей. Переделаем наш предыдущий пример и используем объект Row:

# -*- coding: utf-8 -*-
import sqlite3
con = sqlite3.connect("catalog.db")
con.row_factory = sqlite3.Row
cur = con.cursor()        # Создаем объект-курсор
cur.execute("SELECT * FROM user")
arr = cur.fetchall()
print(type(arr[0]))       # <class 'sqlite3.Row'>
print(len(arr[0]))        # 3
print(arr[0][1])          # Доступ по индексу
print(arr[0]["email"])    # Доступ по названию поля
print(arr[0]["EMAIL"])    # He зависит от регистра символов
for elem in arr[0]:
    print(elem)
print(arr[0].keys())      # ['id_user', 'email', 'passw']
cur.close ()              # Закрываем объект-курсор
con.close ()              # Закрываем соединение
input ()
Архив с файлом можно взять здесь.

    Результат работы приложения:

<class 'sqlite3.Row'> 3 unicross@mail.ru unicross@mail.ru unicross@mail.ru 1 unicross@mail.ru password1 ['id_user', 'email', 'passw']

    Как видно из результатов предыдущих примеров, все данные, имеющие в SQLite тип TEXT, возвращаются в виде строк. В предыдущих шагах мы создали базу данных testdb.db и сохранили данные в полях таблицы в кодировке Windows-1251. Попробуем отобразить записи из таблицы с рубриками:

>>> con = sqlite3.connect ("testdb.db")
>>> cur = con.cursor()
>>> cur.execute ("SELECT * FROM rubr")
<sqlite3.Cursor object at 0x026A1560>
>>> cur.fetchone()
(1, '?ЁюуЁрььшЁютрэшх')
>>> con.close()

    При осуществлении преобразования предполагается, что строка хранится в кодировке UTF-8. Так как в нашем примере мы используем другую кодировку, то получается такой результат. Изменить его позволяет атрибут text_factory объекта соединения. В качестве значения атрибута указывается ссылка на функцию, которая будет использоваться для осуществления преобразования значения текстовых полей. Например, чтобы вернуть последовательность байтов, следует указать ссылку на функцию bytes ():

>>> con = sqlite3.connect ("testdb.db")
>>> con.text_factory = bytes  #  Название функции без круглых скобок!
>>> cur = con.cursor ()
>>> cur.execute ("SELECT * FROM rubr")
<sqlite3.Cursor object at 0x023C6DA0>
>>> cur.fetchone()
(1, b'\xe2\x95\xa7\xd0\x81\xd1\x8e\xd1\x83\xd0\x81\xd1\x80\xd1
\x8c\xd1\x8c\xd1\x88\xd0\x81\xd1\x8e\xd1\x82\xd1\x80\xd1\x8d\xd1\x88\xd1\x85')

    Если необходимо вернуть строку, то внутри функции обратного вызова следует вызвать функцию str() и явно указать кодировку данных. Функция обратного вызова должна принимать один параметр и возвращать преобразованную строку. Выведем текстовые данные в виде строки:

>>> con.text_factory = lambda  s: str (s, "cp1251") 
>>> cur.execute ("SELECT * FROM rubr")
<sqlite3.Cursor object at 0x023C6DA0>
>>> cur.fetchone ()
(1, 'Программирование')
>>> con.close ()

    На следующем шаге мы рассмотрим управление транзакциями.




Предыдущий шаг Содержание Следующий шаг