Comment convertir cette liste de dictionnaires en fichier csv?

160

J'ai une liste de dictionnaires qui ressemble à ceci:

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

Que dois-je faire pour convertir ceci en un fichier csv qui ressemble à ceci:

name,age,weight
bob,25,200
jim,31,180
backus
la source
duplication possible de l'en- tête d'écriture en python csv avec DictWriter
SilentGhost

Réponses:

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

EDIT: Ma solution précédente ne gère pas la commande. Comme l'a noté Wilduck, DictWriter est plus approprié ici.

Matthew Flaschen
la source
11
Notez qu'une manière plus pythonique d'ouvrir (et de fermer) les fichiers estwith open('people.csv', 'wb') as f: ...
gozzilli
6
Vous pouvez utiliser à la dict_writer.writeheader()place dedict_writer.writer.writerow(keys)
megawac
8
Ne fonctionne pas si le premier élément de la liste ne contient pas toutes les clés
greg121
61
dans Python 3 c'estopen('people.csv', 'w')
Zev Averbach
3
set().union(*(d.keys() for d in mylist))pour obtenir toutes les clés de la liste (si vous en avez qui n'ont pas toutes les clés.)
Julian Camilleri
17

c'est lorsque vous avez une liste de dictionnaires:

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'})
haché
la source
17

En python 3, les choses sont un peu différentes, mais beaucoup plus simples et moins sujettes aux erreurs. C'est une bonne idée de dire au CSV que votre fichier doit être ouvert avec un utf8encodage, car cela rend ces données plus portables pour les autres (en supposant que vous n'utilisez pas un encodage plus restrictif, comme 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)
  • Notez qu'en csvpython 3 a besoin du newline=''paramètre, sinon vous obtenez des lignes vierges dans votre CSV lors de l'ouverture dans excel / opencalc.

Alternativement: je préfère utiliser le gestionnaire csv dans le pandasmodule. Je trouve qu'il est plus tolérant aux problèmes d'encodage, et les pandas convertiront automatiquement les numéros de chaîne dans les CSV dans le type correct (int, float, etc.) lors du chargement du fichier.

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

Remarque:

  • pandas se chargera d'ouvrir le fichier pour vous si vous lui donnez un chemin, et sera par défaut utf8en python3, et trouvera également les en-têtes.
  • un dataframe n'est pas la même structure que ce que CSV vous donne, vous ajoutez donc une ligne lors du chargement pour obtenir la même chose: dataframe.to_dict('records')
  • pandas facilite également le contrôle de l'ordre des colonnes dans votre fichier csv. Par défaut, ils sont classés par ordre alphabétique, mais vous pouvez spécifier l'ordre des colonnes. Avec le csvmodule vanilla , vous devez le nourrir OrderedDictou ils apparaîtront dans un ordre aléatoire (si vous travaillez en python <3.5). Voir: Préserver l'ordre des colonnes dans Python Pandas DataFrame pour plus.
Marc Maxmeister
la source
7

Parce que @User et @BiXiC ont demandé de l'aide avec UTF-8, voici une variante de la solution par @Matthew. (Je n'ai pas le droit de commenter, alors je réponds.)

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)
fleur de fleur
la source
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]])

Ce serait le moyen le plus simple d'écrire des données dans un fichier .csv

jitsm555
la source
1

Voici une autre solution plus générale en supposant que vous n'avez pas de liste de lignes (peut-être qu'elles ne tiennent pas en mémoire) ou une copie des en-têtes (peut-être que la write_csvfonction est générique):

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)

Remarque : le constructeur OrderedDict utilisé ici ne préserve que l'ordre en python> 3.4. Si l'ordre est important, utilisez le OrderedDict([('name', 'bob'),('age',25)])formulaire.

Eddygeek
la source
jamais vu personne stocker des données dans un générateur auparavant - approche intéressante.
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
la source