He estado usando la siguiente función para hacer un «más legible» (supuestamente) formato para la obtención de 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

Me gustaría, a continuación, utilizar la función como esta:

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.

Mientras que esto parece funcionar bastante bien bajo diferentes niveles de estrés, me pregunto si hay una manera más eficiente, o «python» manera de hacer esto.

InformationsquelleAutor Nitzle | 2012-05-04

6 Comentarios

  1. 25

    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, utilizando index en situaciones como esta es propensos a contener errores, al menos en situaciones donde el mismo punto pueden ocurrir dos veces en una lista. Uso 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 poca cosa, la verdad. Aquí una versión 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]

    Hágamelo saber si funciona.

    • Funciona como un encanto. Gracias!
    • Lo que si hay que hacer algún post procesamiento de los elementos de cada fila. Entonces esto no iba a funcionar -> [dict(zip(columna, fila)) para la fila del cursor]
    • eso suena como una pregunta nueva para mí. Si alguien no ha preguntado aquí, tal vez debería.
    • La leyenda! Gracias
  2. 10

    De una manera limpia para evitar el uso de memoria de tirar todo en una lista por adelantado, usted podría ajustar el cursor en un generador de función:

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

    A continuación, utilizar la siguiente – filas del cursor se convierten dicts mientras que la iteración:

    for row in rows_as_dicts(cursor):
        item1 = row["col1"]
        item2 = row["col2"]
    • Este es probablemente bueno para conjuntos de resultados grandes, pero me pareció que para ser menos eficientes que @senderle la respuesta relativamente pequeños conjuntos de resultados.
    • Gracias – pude ver que. ¿Tienes alguna números reales diferencia de rendimiento que usted vio?
    • Python también permite a los generadores: for row in (i[0] for i in cursor.description):. No hay necesidad para una función separada.
    • Esa es una gran sugerencia – que tienden a olvidarse de eso!
  3. 4

    Que no se debe usar dict para grandes conjuntos de resultados debido a que el uso de la memoria será enorme. Yo uso cx_Oracle mucho y no tener un buen diccionario cursor me molestó lo suficiente como para escribir un módulo para ello. También tengo que conectar Python para muchas bases de datos diferentes, así que lo hice de una manera que usted puede utilizar con cualquier DB API 2 conector.

    Es en PyPi Gestor de base de datos – Bases de datos más Sencillo

    >>> 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. 0

    Asumir cursor «Cursor» ya está definido y con muchas ganas de ir:

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

    a continuación, usted puede ir:

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

    No es tan limpio y suave como si el sistema se maneja a sí mismo, pero no es horrible.

  5. 0

    Crear un diccionario

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

    Acceso:

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

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

Dejar respuesta

Please enter your comment!
Please enter your name here