¿Cómo convierto esta lista de diccionarios a un archivo csv?

160

Tengo una lista de diccionarios que se parece a esto:

toCSV = [{'name':'bob','age':25,'weight':200},{'name':'jim','age':31,'weight':180}]

¿Qué debo hacer para convertir esto a un archivo csv que se parece a esto?

name,age,weight
bob,25,200
jim,31,180
backus
fuente
posible duplicado del encabezado
SilentGhost

Respuestas:

284
import csv
toCSV = [{'name':'bob','age':25,'weight':200},
         {'name':'jim','age':31,'weight':180}]
keys = toCSV[0].keys()
with open('people.csv', 'wb') as output_file:
    dict_writer = csv.DictWriter(output_file, keys)
    dict_writer.writeheader()
    dict_writer.writerows(toCSV)

EDITAR: Mi solución anterior no maneja el pedido. Como señaló Wilduck, DictWriter es más apropiado aquí.

Matthew Flaschen
fuente
11
Tenga en cuenta que una forma más pitónica de abrir (y cerrar) archivos eswith open('people.csv', 'wb') as f: ...
gozzilli
66
Puede usar en dict_writer.writeheader()lugar dedict_writer.writer.writerow(keys)
megawac
8
No funciona si el primer elemento de la lista no contiene todas las claves
greg121
61
en Python 3 esopen('people.csv', 'w')
Zev Averbach
3
set().union(*(d.keys() for d in mylist))para obtener todas las claves de la lista (si tiene algunas que no tienen todas las claves)
Julian Camilleri
17

Esto es cuando tienes una lista de diccionario:

import csv
with open('names.csv', 'w') as csvfile:
    fieldnames = ['first_name', 'last_name']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
Hammed
fuente
17

En Python 3 las cosas son un poco diferentes, pero mucho más simples y menos propensas a errores. Es una buena idea decirle al CSV que su archivo debe abrirse con utf8codificación, ya que hace que los datos sean más portátiles para otros (suponiendo que no esté utilizando una codificación más restrictiva, como latin1)

import csv
toCSV = [{'name':'bob','age':25,'weight':200},
         {'name':'jim','age':31,'weight':180}]
with open('people.csv', 'w', encoding='utf8', newline='') as output_file:
    fc = csv.DictWriter(output_file, 
                        fieldnames=toCSV[0].keys(),

                       )
    fc.writeheader()
    fc.writerows(toCSV)
  • Tenga csven cuenta que en python 3 necesita el newline=''parámetro, de lo contrario, obtendrá líneas en blanco en su CSV al abrir en excel / opencalc.

Alternativamente: prefiero usar el controlador csv en el pandasmódulo. Creo que es más tolerante a los problemas de codificación, y los pandas convertirán automáticamente los números de cadena en CSV en el tipo correcto (int, float, etc.) al cargar el archivo.

import pandas
dataframe = pandas.read_csv(filepath)
list_of_dictionaries = dataframe.to_dict('records')
dataframe.to_csv(filepath)

Nota:

  • pandas se encargará de abrir el archivo por usted si le da una ruta, y se configurará de manera predeterminada utf8en python3, y también descubrirá los encabezados.
  • un marco de datos no tiene la misma estructura que lo que le ofrece CSV, por lo que agrega una línea al cargar para obtener lo mismo: dataframe.to_dict('records')
  • pandas también hace que sea mucho más fácil controlar el orden de las columnas en su archivo csv. Por defecto, son alfabéticos, pero puede especificar el orden de las columnas. Con el csvmódulo vanilla , debe alimentarlo OrderedDicto aparecerán en un orden aleatorio (si trabaja en python <3.5). Ver: Preservar el orden de las columnas en Python Pandas DataFrame para más información.
Marc Maxmeister
fuente
7

Porque @User y @BiXiC pidieron ayuda con UTF-8 aquí una variación de la solución de @Matthew. (No se me permite comentar, así que estoy respondiendo).

import unicodecsv as csv
toCSV = [{'name':'bob','age':25,'weight':200},
         {'name':'jim','age':31,'weight':180}]
keys = toCSV[0].keys()
with open('people.csv', 'wb') as output_file:
    dict_writer = csv.DictWriter(output_file, keys)
    dict_writer.writeheader()
    dict_writer.writerows(toCSV)
flor de flor
fuente
2
import csv

with open('file_name.csv', 'w') as csv_file:
    writer = csv.writer(csv_file)
    writer.writerow(('colum1', 'colum2', 'colum3'))
    for key, value in dictionary.items():
        writer.writerow([key, value[0], value[1]])

Esta sería la forma más sencilla de escribir datos en un archivo .csv

jitsm555
fuente
1

Aquí hay otra solución más general, suponiendo que no tenga una lista de filas (tal vez no quepan en la memoria) o una copia de los encabezados (tal vez la write_csvfunción sea genérica):

def gen_rows():
    yield OrderedDict(name='bob', age=25, weight=200)
    yield OrderedDict(name='jim', age=31, weight=180)

def write_csv():
    it = genrows()
    first_row = it.next()  # __next__ in py3
    with open("people.csv", "w") as outfile:
        wr = csv.DictWriter(outfile, fieldnames=list(first_row))
        wr.writeheader()
        wr.writerow(first_row)
        wr.writerows(it)

Nota : el constructor OrderedDict utilizado aquí solo conserva el orden en python> 3.4. Si el orden es importante, use el OrderedDict([('name', 'bob'),('age',25)])formulario.

eddygeek
fuente
Nunca vi a nadie almacenar datos en un generador antes - enfoque interesante.
Marc Maxmeister
1
import csv
toCSV = [{'name':'bob','age':25,'weight':200},
         {'name':'jim','age':31,'weight':180}]
header=['name','age','weight']     
try:
   with open('output'+str(date.today())+'.csv',mode='w',encoding='utf8',newline='') as output_to_csv:
       dict_csv_writer = csv.DictWriter(output_to_csv, fieldnames=header,dialect='excel')
       dict_csv_writer.writeheader()
       dict_csv_writer.writerows(toCSV)
   print('\nData exported to csv succesfully and sample data')
except IOError as io:
    print('\n',io)
Souvik Daw
fuente