Создание списка слов с помощью 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 (eg 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. 

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

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

  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] 

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

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

 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"] 

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

Это на базе PyPi DBMS – упрощенные базы данных

 >>> 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'] 

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

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"]]

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

Создать дикт

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

Для доступа:

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

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

 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)