Создание списка слов с помощью 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.
Хотя это, кажется, довольно хорошо работает при различных уровнях стресса, мне интересно, есть ли более эффективный или "питонический" способ сделать это.
Ответы
Ответ 1
Есть и другие улучшения, но это действительно выскочило на меня:
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]
Сообщите мне, если это работает.
Ответ 2
Для того, чтобы избежать использования памяти для сброса всего в списке вверх, вы можете поместить курсор в функцию генератора:
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"]
Ответ 3
Вы не должны использовать dict для больших наборов результатов, потому что использование памяти будет огромным. Я часто использую cx_Oracle и не имею хорошего словарного курсора, который меня беспокоил, чтобы написать модуль для него. Я также должен подключать 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
Предположим, что курсор "Курсор" уже определен и доступен:
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"]]
Не так чисто и гладко, как если бы система обрабатывала его сама, но не ужасно.
Ответ 5
Создайте файл dict
cols=dict()
for col, desc in enumerate(cur.description):
cols[desc[0]] = col
Для доступа:
for result in cur
print (result[cols['COL_NAME']])
Ответ 6
У меня лучший вариант:
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)