Выносимые данные из бд как переменные

Как выводимые данные из БД с помощью SELECT * FROM table1 ORDER BY money DESC LIMIT 10; сделaть переменными на выходе?


Ответы (2 шт):

Автор решения: Daniil Loban

Вот небольшой пример, разумеется не зная что вам нужно и не видя ваших попыток сложно судить о том что именно у вас не получается:

import sqlite3

con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.executescript("create table table1(human,money);")

cur.execute("insert into table1(human, money) values ('Леонид Михельсон', 24000 );")
cur.execute("insert into table1(human, money) values ('Владимир Лисин', 21300 );")
cur.execute("insert into table1(human, money) values ('Вагит Алекперов', 20700  );")
cur.execute("insert into table1(human, money) values ('Алексей Мордашов и семья', 20500  );")
cur.execute("insert into table1(human, money) values ('Геннадий Тимченко', 20100 );")
cur.execute("insert into table1(human, money) values ('Владимир Потанин', 18100   );")
cur.execute("insert into table1(human, money) values ('Михаил Фридман', 15000  );")
cur.execute("insert into table1(human, money) values ('Андрей Мельниченко', 13800 );")
cur.execute("insert into table1(human, money) values ('Алишер Усманов', 12600)")
cur.execute("insert into table1(human, money) values ('Роман Абрамович', 12400 );")
cur.execute("insert into table1(human, money) values ('Виктор Вексельберг', 11500 );")
cur.execute("insert into table1(human, money) values ('Михаил Прохоров', 9800 );")
cur.execute("insert into table1(human, money) values ('Герман Хан', 9700 );")
cur.execute("insert into table1(human, money) values ('Виктор Рашников', 8900 );")
cur.execute("insert into table1(human, money) values ('Леонид Федун и семья', 8700 );")

# делаем из результата массив
rows = [row for row in con.execute('SELECT * FROM table1 ORDER BY money DESC LIMIT 10;')]

# выводим
print(rows)
con.close()

Вывод будет таким:

[('Леонид Михельсон', 24000), ('Владимир Лисин', 21300), ('Вагит Алекперов', 20700), ('Алексей Мордашов и семья', 20500), ('Геннадий Тимченко', 20100), ('Владимир Потанин', 18100), ('Михаил Фридман', 15000), ('Андрей Мельниченко', 13800), ('Алишер Усманов', 12600), ('Роман Абрамович', 12400)]

еще

[first, num2, num3, num4, num5, num6, num7, num8, num9, last ] = rows
print(first)
print(last)

Вывод будет таким:

('Леонид Михельсон', 24000)
('Роман Абрамович', 12400)
→ Ссылка
Автор решения: Vasyl Kolomiets

Вариант 1. Использовать механизм отображения полей вашей БД на элементы словаря, где в качестве ключа используется имя столбца. Но сразу посоветую - учитесь читать документацию на английском. Вот пример из документации по SQLite. Перевел автопереводчиком, но можно сразу смотреть пример:

class sqlite3.Row
Он поддерживает доступ к отображению по имени и индексу столбца, итерацию, представление, проверку равенства и len().

keys() Этот метод возвращает список имен столбцов. Сразу после запроса это первый член каждого кортежа в Cursor.description Предположим, мы инициализируем таблицу, как в приведенном примере:

import sqlite3

conn = sqlite3.connect(":memory:")
c = conn.cursor()
c.execute('''create table stocks
             (date text, trans text, symbol text, qty real, price real)''')
c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""")
conn.commit()
c.close()

Теперь подключаем класс Row:

>>> conn.row_factory = sqlite3.Row

и можно обращаться к полям базы по ключу - имени столбца:

>>> c = conn.cursor()
>>> c.execute('select * from stocks')
<sqlite3.Cursor object at 0x7f4e7dd8fa80>
>>> r = c.fetchone()
>>> type(r)
<class 'sqlite3.Row'>
>>> tuple(r)
('2006-01-05', 'BUY', 'RHAT', 100.0, 35.14)
>>> len(r)
5
>>> r[2]
'RHAT'
>>> r.keys()
['date', 'trans', 'symbol', 'qty', 'price']
>>> r['qty']
100.0
>>> for member in r:
...     print(member)
...
2006-01-05
BUY
RHAT
100.0
35.14

Такой подход лучше описанного использования списка переменных в лоб тем, что не нужно заботиться о добавлении ручками еще одного имени столбца в тело запроса, что упрощает кодирование.

Вариант 2. Использование dataclass. Вот пример кода из реальной задачи. Для упрощения понимания сути скажу - в базе хранится информация об отчетах, сохраненных на диск в файлах:

from dataclasses import dataclass

@dataclass
class ScheduledReport:
    """структура для работы с отчетами, поставленными в очередь."""

    id_sheduled: int = 0
    task_id: int = 0
    report_id: int = 0
    start_time: str = ""
    amzn_rprt_id: str = ""
    date_from: str = ""
    date_to: str = ""
    restart_time: str = ""
    status: str = ""
    saved: bool = False
    filename: str = ""

Теперь можно создать объект с многими именованными полями, например так:

new_rep = ScheduledReport(0,1,2)

и обратится к полю по имени:

>>>print(new_rep.report_id)
2

Тогда так может выглядеть функция, выбирающая из базы список dataclass-ов объектов, для каждой записи, где не стоит отметка "сохранен"

def get_sсheduled_reports(c):
    """
    Take from DB sсheduled reports with theirs statuses.

    Parameters
    ----------
    c : cursor to SQLite DB

    Returns
    -------
    list   of sсheduled to DB reports
    """
    sсhedule = c.execute('SELECT * FROM reports_sсheduled WHERE not saved').fetchall()
    return [ScheduledReport(*sсheduled) for sсheduled in sсhedule
            if sсheduled[7] <= datetime_now_iso_str()]  # restart_time <= now()

нужно понимать, что sсheduled[7] содержит признак restart_time, по которому ведется проверка. Однако лучше, было в этом коде использовать как в предыдущем примере c.row_factory = sqlite3.Row, тогда вместо sсheduled[7] написали бы sсheduled["restart_time"], поскольку у меня поля структуры dataclass совпадают с именами полей базы данных.

Вариант 3. Часто - самый лучший. Использовать ORM - системы, например SQLAlchemy. Тут надо много рассказывать, поэтому вам придется самостоятельно почитать )). Вот ссылка на вики

Вариант 4. "На скору руку". Как написали в предыдущем ответе - руками написать список переменных. Тогда приведенная выше функция выглядела бы так:

def get_sсheduled_reports(c):
    """
    Take from DB sсheduled reports with theirs statuses.

    Parameters
    ----------
    c : cursor to SQLite DB

    Returns
    -------
    list   of sсheduled to DB reports
    """
    sсhedule = c.execute('SELECT * FROM reports_sсheduled WHERE not saved').fetchall()
    return [(id_sheduled, task_id, report_id, start_time, amzn_rprt_id, date_from, date_to, restart_time, status, saved, filename) for sсheduled in sсhedule
            if sсheduled[7] <= datetime_now_iso_str()]  # restart_time <= now()

Сами видите, насколько это громоздко при сколько-нибудь осмысленной задаче.

Итоговый совет. В вашем случае я бы посоветовал изучить способ, приведенный мною как Вариант1.... Думаю, вы скоро убедитесь в преимуществах такого подхода. Если ваша база не SQLite - нужно просто почитать документацию. Вот как это делается например, для MySql:

cnx = mysql.connector.connect(database='world')
cursor = cnx.cursor(dictionary=True)
cursor.execute("SELECT * FROM country WHERE Continent = 'Europe'")

print("Countries in Europe:")
for row in cursor:
    print("* {Name}".format(Name=row['Name']

То есть достаточно добавить параметр dictionary=True - и можно пользоваться отображением полей БД на словарь.

Ввиду того, что dbapi в Python стандартизировано соответствующим PEP - стандартом, вы можете убедиться, что именно отображение полей базы в элементы словаря является общепринятым ввиду удобности.

→ Ссылка