it-swarm.com.ru

Создание списка словарей с помощью cx_Oracle

Я использовал следующую функцию, чтобы сделать «более читаемый» (предположительно) формат для извлечения данных из Oracle. Вот функция:

def rows_to_dict_list(cursor):
    """ 
    Create a list, each item contains a dictionary outlined like so:
    { "col1_name" : col1_data }
    Each item in the list is technically one row of data with named columns,
    represented as a dictionary object
    For example:
    list = [
        {"col1":1234567, "col2":1234, "col3":123456, "col4":BLAH},
        {"col1":7654321, "col2":1234, "col3":123456, "col4":BLAH}
    ]
    """

    # Get all the column names of the query.
    # Each column name corresponds to the row index
    # 
    # cursor.description returns a list of tuples, 
    # with the 0th item in the Tuple being the actual column name.
    # everything after i[0] is just misc Oracle info (e.g. datatype, size)
    columns = [i[0] for i in cursor.description]

    new_list = []
    for row in cursor:
        row_dict = dict()
        for col in columns:
            # Create a new dictionary with field names as the key, 
            # row data as the value.
            #
            # Then add this dictionary to the new_list
            row_dict[col] = row[columns.index(col)]

        new_list.append(row_dict)
    return new_list

Затем я бы использовал функцию следующим образом:

sql = "Some kind of SQL statement"
curs.execute(sql)
data = rows_to_dict_list(curs)
#
for row in data:
    item1 = row["col1"]
    item2 = row["col2"]
    # Do stuff with item1, item2, etc...
    # You don't necessarily have to assign them to variables,
    # but you get the idea.

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

18
Nitzle

Есть и другие улучшения, но это действительно выскочило на меня:

    for col in columns:
        # Create a new dictionary with field names as the key, 
        # row data as the value.
        #
        # Then add this dictionary to the new_list
        row_dict[col] = row[columns.index(col)]

Помимо неэффективности, использование index в подобных ситуациях подвержено ошибкам, по крайней мере, в ситуациях, когда один и тот же элемент может встречаться в списке дважды. Вместо этого используйте enumerate:

    for i, col in enumerate(columns):
        # Create a new dictionary with field names as the key, 
        # row data as the value.
        #
        # Then add this dictionary to the new_list
        row_dict[col] = row[i]

Но это маленькая картошка, правда. Вот гораздо более компактная версия этой функции:

def rows_to_dict_list(cursor):
    columns = [i[0] for i in cursor.description]
    return [dict(Zip(columns, row)) for row in cursor]

Дай мне знать, если это работает.

25
senderle

Чтобы избежать использования памяти при выводе всего списка заранее, вы можете заключить курсор в функцию генератора:

def rows_as_dicts(cursor):
    """ returns cx_Oracle rows as dicts """
    colnames = [i[0] for i in cursor.description]
    for row in cursor:
        yield dict(Zip(colnames, row))

Затем используйте следующее - строки из курсора преобразуются в dicts при итерации:

for row in rows_as_dicts(cursor):
    item1 = row["col1"]
    item2 = row["col2"]
10
Josh Werts

Вы не должны использовать dict для больших наборов результатов, потому что использование памяти будет огромным. Я часто использую cx_Oracle и не имею курсора Nice Dictionary, который надоел мне, чтобы написать для него модуль. Я также должен подключить Python ко многим различным базам данных, поэтому я сделал это так, чтобы вы могли использовать его с любым соединителем DB API 2.

Это работает на PyPi СУБД - базы данных сделаны проще

>>> import dbms
>>> db = dbms.OraConnect('myUser', 'myPass', 'myInstance')
>>> cur = db.cursor()
>>> cur.execute('SELECT * FROM people WHERE id = :id', {'id': 1123})
>>> row = cur.fetchone()
>>> row['last_name']
Bailey
>>> row.last_name
Bailey
>>> row[3]
Bailey
>>> row[0:4]
[1123, 'Scott', 'R', 'Bailey']
4
Scott Bailey

Предположим, что курсор «Курсор» уже определен и идет в путь:

byCol = {cl:i for i,(cl,type, a, b, c,d,e) in enumerate(Cursor.description)}

тогда вы можете просто пойти: 

for row in Cursor: column_of_interest = row[byCol["COLUMN_NAME_OF_INTEREST"]]

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

0
The Nate

Создать дикт

cols=dict()
for col, desc in enumerate(cur.description):
    cols[desc[0]] = col

Для доступа:

for result in cur
    print (result[cols['COL_NAME']])
0
jdex

У меня есть лучший

import cx_Oracle

def makedict(cursor):
"""Convert cx_Oracle query result to be a dictionary   
"""
cols = [d[0] for d in cursor.description]

def createrow(*args):
    return dict(Zip(cols, args))

return createrow

db = cx_Oracle.connect('user', 'pw', 'Host')
cursor = db.cursor()
rs = cursor.execute('SELECT * FROM Tablename')
cursor.rowfactory = makedict(cursor)
0
YellowTree