resueltos recorrer lista elementos ejercicios diccionarios diccionario dentro convertir anidados agregar python oracle cx-oracle

python - recorrer - Hacer una lista de diccionarios con cx_Oracle



lista de diccionarios python (6)

Crear un dict

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

Acceder:

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

He estado usando la siguiente función para hacer un formato "más legible" (supuestamente) para obtener datos de Oracle. Aquí está la función:

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

Entonces usaría la función así:

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.

Si bien esto parece funcionar bastante bien bajo diferentes niveles de estrés, me pregunto si hay una forma más eficiente o "pitónica" de hacer esto.


Hay otras mejoras que hacer, pero esto realmente me llamó la atención:

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

Además de ser ineficiente, el uso del index en situaciones como esta es propenso a errores, al menos en situaciones donde el mismo elemento puede aparecer dos veces en una lista. Utilice enumerate lugar:

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]

Pero eso es papas pequeñas, de verdad. Aquí hay una versión mucho más compacta de esta función:

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

Déjame saber si eso funciona.


No debe usar dict para grandes conjuntos de resultados porque el uso de la memoria será enorme. Uso mucho cx_Oracle y no tengo un buen diccionario que me haya molestado lo suficiente como para escribir un módulo para él. También tengo que conectar Python a muchas bases de datos diferentes, así que lo hice de una manera que puede usar con cualquier conector DB API 2.

Está en PyPi DBMS - Bases de datos simplificadas

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


Para obtener una manera limpia de evitar el uso de la memoria de descargar todo en una lista por adelantado, puede ajustar el cursor en una función de generador:

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))

Luego use de la siguiente manera: las filas del cursor se convierten a dictados mientras se repite:

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


Supongamos que el cursor "Cursor" ya está definido y listo para ir:

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

entonces solo puedes ir

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

No tan limpio y suave como si el sistema lo manejara solo, pero no horrible.


Tengo una mejor

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)