nor - Resultados del cursor pyodbc como diccionario python
pyodbc.connect python (5)
¡Suponiendo que sabes los nombres de las columnas! Además, aquí hay tres soluciones diferentes,
¡Probablemente quieras mirar el último!
colnames = [''city'', ''area'', ''street'']
data = {}
counter = 0
for row in x.fetchall():
if not counter in data:
data[counter] = {}
colcounter = 0
for colname in colnames:
data[counter][colname] = row[colcounter]
colcounter += 1
counter += 1
Esa es una versión indexada, no es la solución más hermosa, pero funcionará. Otro sería indexar el nombre de la columna como clave del diccionario con una lista dentro de cada clave que contiene los datos en orden de número de fila. haciendo:
colnames = [''city'', ''area'', ''street'']
data = {}
for row in x.fetchall():
colindex = 0
for col in colnames:
if not col in data:
data[col] = []
data[col].append(row[colindex])
colindex += 1
Al escribir esto, entiendo que hacer for col in colnames
podría reemplazarse por for colindex in range(0, len())
pero se entiende la idea. El último ejemplo sería útil cuando no se obtienen todos los datos, sino una fila a la vez, por ejemplo:
Usando dict para cada fila de datos
def fetchone_dict(stuff):
colnames = [''city'', ''area'', ''street'']
data = {}
for colindex in range(0, colnames):
data[colnames[colindex]] = stuff[colindex]
return data
row = x.fetchone()
print fetchone_dict(row)[''city'']
Obteniendo nombres de tablas (creo ... gracias a Foo Stack):
una solución más directa de Beargle a continuación!
cursor.execute("SELECT sys.objects.name, sys.columns.name FROM sys.objects INNER JOIN sys.columns ON sys.objects.object_id = sys.columns. object_id WHERE sys.objects.type = ''U'';")
schema = {}
for it in cursor.fetchall():
if it[0] in schema:
schema[it[0]].append(it[1])
else:
schema[it[0]] = [it[1]]
¿Cómo serializo la salida del cursor de pyodbc (de .fetchone
, .fetchmany
o .fetchall
) como un diccionario de Python?
Estoy usando bottlepy y necesito devolver el dict para que pueda devolverlo como JSON.
Principalmente saliendo de la respuesta @Torxed, creé un conjunto completo de funciones para encontrar el esquema y los datos en un diccionario:
def schema_dict(cursor):
cursor.execute("SELECT sys.objects.name, sys.columns.name FROM sys.objects INNER JOIN sys.columns ON sys.objects.object_id = sys.columns. object_id WHERE sys.objects.type = ''U'';")
schema = {}
for it in cursor.fetchall():
if it[0] not in schema:
schema[it[0]]={''scheme'':[]}
else:
schema[it[0]][''scheme''].append(it[1])
return schema
def populate_dict(cursor, schema):
for i in schema.keys():
cursor.execute("select * from {table};".format(table=i))
for row in cursor.fetchall():
colindex = 0
for col in schema[i][''scheme'']:
if not ''data'' in schema[i]:
schema[i][''data'']=[]
schema[i][''data''].append(row[colindex])
colindex += 1
return schema
def database_to_dict():
cursor = connect()
schema = populate_dict(cursor, schema_dict(cursor))
Siéntase libre de usar todo el código de golf en esto para reducir las líneas; ¡Pero mientras tanto, funciona!
;)
Usando el resultado de @Bargle con Bottlepy, pude crear esta consulta muy concisa exponiendo el punto final:
@route(''/api/query/<query_str>'')
def query(query_str):
cursor.execute(query_str)
return {''results'':
[dict(zip([column[0] for column in cursor.description], row))
for row in cursor.fetchall()]}
Si no conoce las columnas con anticipación, use cursor.description para compilar una lista de nombres de columnas y zip con cada fila para generar una lista de diccionarios. El ejemplo supone que la conexión y la consulta están compiladas:
>>> cursor = connection.cursor().execute(sql)
>>> columns = [column[0] for column in cursor.description]
>>> print columns
[''name'', ''create_date'']
>>> results = []
>>> for row in cursor.fetchall():
... results.append(dict(zip(columns, row)))
...
>>> print results
[{''create_date'': datetime.datetime(2003, 4, 8, 9, 13, 36, 390000), ''name'': u''master''},
{''create_date'': datetime.datetime(2013, 1, 30, 12, 31, 40, 340000), ''name'': u''tempdb''},
{''create_date'': datetime.datetime(2003, 4, 8, 9, 13, 36, 390000), ''name'': u''model''},
{''create_date'': datetime.datetime(2010, 4, 2, 17, 35, 8, 970000), ''name'': u''msdb''}]
Aquí hay una versión de formulario corta que podría usar
>>> cursor.select("<your SQL here>")
>>> single_row = dict(zip(zip(*cursor.description)[0], cursor.fetchone()))
>>> multiple_rows = [dict(zip(zip(*cursor.description)[0], row)) for row in cursor.fetchall()]
Como sabrá cuando agrega * a una lista, básicamente borra la lista, dejando las entradas de la lista individual como parámetros para la función a la que está llamando. Al usar el código postal, seleccionamos la entrada de la 1ª a la ny las ajustamos como una cremallera en sus pantalones.
entonces al usar
zip(*[(a,1,2),(b,1,2)])
# interpreted by python as zip((a,1,2),(b,1,2))
usted obtiene
[(''a'', ''b''), (1, 1), (2, 2)]
Como la descripción es una tupla con tuplas, donde cada tupla describe el encabezado y el tipo de datos para cada columna, puede extraer la primera de cada tupla con
>>> columns = zip(*cursor.description)[0]
equivalente a
>>> columns = [column[0] for column in cursor.description]