Como converter esta lista de dicionários em um arquivo csv?

160

Eu tenho uma lista de dicionários que se parece com isso:

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

O que devo fazer para converter isso em um arquivo csv parecido com este:

name,age,weight
bob,25,200
jim,31,180
backus
fonte
possível duplicata de escrever cabeçalho em python csv com DictWriter
SilentGhost

Respostas:

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)

EDIT: Minha solução anterior não lida com o pedido. Conforme observado por Wilduck, o DictWriter é mais apropriado aqui.

Matthew Flaschen
fonte
11
Note-se que uma maneira mais Python de abertura (e fechamento) arquivos éwith open('people.csv', 'wb') as f: ...
gozzilli
6
Você pode usar em dict_writer.writeheader()vez dedict_writer.writer.writerow(keys)
megawac
8
Não funciona se o item primeira lista não contém todas as chaves
greg121
61
em Python 3 éopen('people.csv', 'w')
Zev Averbach 10/10
3
set().union(*(d.keys() for d in mylist))para obter todas as chaves na lista (se você tem algum que não tem todas as chaves.)
Julian Camilleri
17

é quando você tem uma lista de dicionários:

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'})
odiado
fonte
17

No python 3, as coisas são um pouco diferentes, mas muito mais simples e menos propensas a erros. É uma boa idéia informar ao CSV que seu arquivo deve ser aberto com utf8codificação, pois torna esses dados mais portáteis para outras pessoas (supondo que você não esteja usando uma codificação mais restritiva, 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)
  • Observe que csvno python 3 precisa do newline=''parâmetro, caso contrário, você obtém linhas em branco no seu CSV ao abrir no excel / opencalc.

Como alternativa: prefiro usar o manipulador csv no pandasmódulo. Acho que é mais tolerante a problemas de codificação, e os pandas convertem automaticamente os números de string em CSVs no tipo correto (int, float, etc.) ao carregar o arquivo.

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

Nota:

  • Os pandas cuidarão de abrir o arquivo para você, se você der um caminho, e usará como padrão utf8 python3, além de descobrir os cabeçalhos.
  • um dataframe não é a mesma estrutura que o CSV fornece, então você adiciona uma linha ao carregar para obter a mesma coisa: dataframe.to_dict('records')
  • O pandas também facilita muito o controle da ordem das colunas no seu arquivo csv. Por padrão, eles são alfabéticos, mas você pode especificar a ordem das colunas. Com o csvmódulo vanilla , você precisa alimentá-lo OrderedDictou eles aparecerão em uma ordem aleatória (se estiver trabalhando em python <3.5). Consulte: Preservando a ordem das colunas no Python Pandas DataFrame para obter mais informações.
Marc Maxmeister
fonte
7

Como o @User e o @BiXiC pediram ajuda com o UTF-8 aqui uma variação da solução do @Matthew. (Não tenho permissão para comentar, por isso estou respondendo.)

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

Essa seria a maneira mais simples de gravar dados no arquivo .csv

jitsm555
fonte
1

Aqui está outra solução mais geral, supondo que você não tenha uma lista de linhas (talvez elas não se encaixem na memória) ou uma cópia dos cabeçalhos (talvez a write_csvfunção seja 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 : o construtor OrderedDict usado aqui preserva apenas a ordem em python> 3.4. Se a ordem for importante, use o OrderedDict([('name', 'bob'),('age',25)])formulário.

eddygeek
fonte
nunca vi ninguém armazenar dados em um gerador antes - abordagem interessante.
Marc Maxmeister 13/02/19
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
fonte