Jak przekonwertować tę listę słowników do pliku CSV?

160

Mam listę słowników, która wygląda mniej więcej tak:

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

Co powinienem zrobić, aby przekonwertować to na plik CSV, który wygląda mniej więcej tak:

name,age,weight
bob,25,200
jim,31,180
backus
źródło
możliwy duplikat zapisu nagłówka w csv python z DictWriter
SilentGhost

Odpowiedzi:

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)

EDYCJA: Moje poprzednie rozwiązanie nie obsługuje zamówienia. Jak zauważył Wilduck, DictWriter jest tutaj bardziej odpowiedni.

Matthew Flaschen
źródło
11
Zauważ, że bardziej pythonowym sposobem otwierania (i zamykania) plików jestwith open('people.csv', 'wb') as f: ...
gozzilli
6
Możesz użyć dict_writer.writeheader()zamiastdict_writer.writer.writerow(keys)
megawac
8
Nie działa, jeśli pierwsza pozycja listy nie zawiera wszystkich kluczy
greg121
61
w Pythonie 3 toopen('people.csv', 'w')
Zev Averbach
3
set().union(*(d.keys() for d in mylist))aby uzyskać wszystkie klucze z listy (jeśli masz takie, które nie mają wszystkich kluczy).
Julian Camilleri
17

tak jest, gdy masz jedną listę słowników:

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'})
hamed
źródło
17

W Pythonie 3 rzeczy są trochę inne, ale o wiele prostsze i mniej podatne na błędy. Dobrym pomysłem jest poinformowanie CSV, że plik powinien zostać otwarty z utf8kodowaniem, ponieważ sprawia, że ​​dane są bardziej przenośne dla innych (zakładając, że nie używasz bardziej restrykcyjnego kodowania, np. 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)
  • Zwróć uwagę, że csvw Pythonie 3 potrzebny jest newline=''parametr, w przeciwnym razie podczas otwierania w programie excel / opencalc otrzymasz puste wiersze w pliku CSV.

Alternatywnie: wolę używać programu obsługi csv w pandasmodule. Uważam, że jest bardziej tolerancyjny na problemy z kodowaniem, a pandy automatycznie konwertują liczby ciągów w plikach CSV na właściwy typ (int, float itp.) Podczas ładowania pliku.

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

Uwaga:

  • pandy zajmą się otwarciem pliku, jeśli podasz mu ścieżkę, i domyślnie utf8 w python3, a także ustalą nagłówki.
  • ramka danych nie jest tą samą strukturą, jaką daje CSV, więc dodajesz jedną linię po załadowaniu, aby uzyskać to samo: dataframe.to_dict('records')
  • pandy znacznie ułatwiają także kontrolowanie kolejności kolumn w pliku csv. Domyślnie są alfabetyczne, ale możesz określić kolejność kolumn. Z csvmodułem waniliowym , musisz go podać OrderedDictlub pojawią się w losowej kolejności (jeśli pracujesz w pythonie <3.5). Zobacz: Zachowywanie kolejności kolumn w Python Pandas DataFrame, aby uzyskać więcej informacji.
Marc Maxmeister
źródło
7

Ponieważ @User i @BiXiC poprosili o pomoc z UTF-8 tutaj wariant rozwiązania autorstwa @Matthew. (Nie mogę komentować, więc odpowiadam.)

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)
kwiatek
źródło
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]])

Byłby to najprostszy sposób zapisania danych do pliku .csv

jitsm555
źródło
1

Oto inne, bardziej ogólne rozwiązanie, przy założeniu, że nie masz listy wierszy (być może nie mieszczą się w pamięci) lub kopii nagłówków (być może write_csvfunkcja jest ogólna):

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)

Uwaga : użyty tutaj konstruktor OrderedDict zachowuje tylko kolejność w Pythonie> 3.4. Jeśli zamówienie jest ważne, skorzystaj z OrderedDict([('name', 'bob'),('age',25)])formularza.

eddygeek
źródło
nigdy wcześniej nie widziałem nikogo, kto przechowuje dane w generatorze - ciekawe podejście.
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
źródło