2011-12-31 17 views
53

Ho un dizionario:Python: Scrivi dizionario in un file CSV con una riga per ogni 'chiave: valore'

mydict = {key1: value_a, key2: value_b, key3: value_c}

voglio scrivere i dati in un file dict.csv , in questo stile:

key1: value_a 
key2: value_b 
key3: value_c 

ho scritto:

import csv 
f = open('dict.csv','wb') 
w = csv.DictWriter(f,mydict.keys()) 
w.writerow(mydict) 
f.close() 

Ma ora ho tutte le chiavi in ​​una riga e tutto valu es nella riga successiva ..

Quando riesco a scrivere un file come questo, voglio anche leggerlo in un nuovo dizionario.

Giusto per spiegare il mio codice, il dizionario contiene valori e bool da textctrls e checkbox (usando wxpython). Voglio aggiungere i pulsanti "Salva impostazioni" e "Carica impostazioni". Le impostazioni di salvataggio devono scrivere il dizionario nel file nel modo menzionato (per facilitare all'utente la modifica diretta del file csv), le impostazioni di caricamento dovrebbero leggere dal file e aggiornare i textctrls e le caselle di controllo.

+1

puoi fornire un esempio migliore di ciò che vuoi come output? lo "stile" che hai sopra non è CSV. stai cercando 'key1, value_a [linebreak] key2, value_b [linebreak] key3, value_c'? – tkone

+0

Un altro approccio è usare 'repr()' per scrivere il dettato e poi valutare la stringa quando la leggi. Guarda questo [vecchio post SO] (http://stackoverflow.com/questions/1436703/difference- tra-str-e-repr-in-python) per una discussione di 'str()' vs. 'repr()', e [i documenti] (http://docs.python.org/library/functions.html #repr), anche. –

+0

Oltre alla mia risposta qui sotto, se si preferisce qualcosa di un po 'più sofisticato di un semplice file CSV, si consiglia di controllare il modulo 'ConfigParser' –

risposta

121

Il DictWriter non funziona nel modo previsto.

with open('dict.csv', 'wb') as csv_file: 
    writer = csv.writer(csv_file) 
    for key, value in mydict.items(): 
     writer.writerow([key, value]) 

Per leggere di nuovo:

with open('dict.csv', 'rb') as csv_file: 
    reader = csv.reader(csv_file) 
    mydict = dict(reader) 

che è abbastanza compatto, ma presuppone che non c'è bisogno di fare qualsiasi conversione di tipo quando si legge

+1

Mmh ... Ho appena notato che volevi un formato specifico che non fosse esattamente simile a CSV. Supposto che tu volessi lo stile CSV (cioè una riga per coppia chiave-valore) perché stavi usando il modulo CSV ... –

+2

Oppure ... nel caso in cui l'approccio CSV è esattamente quello che volevi, ma preferisci ":" come un separatore, basta aggiungere 'delimiter = ':'' quando si crea lo scrittore e il lettore :) –

+0

la scrittura e la lettura funziona bene ora, ma vorrei anche aggiornare le mie checkbox e textctrls in base ai valori nel mio dizionario. Ho tutti i miei widget in "def create_controls", che viene chiamato quando avvio il mio programma. Ma semplicemente richiamarlo dopo aver letto dal mio csv non aggiorna lo stato dei miei widget ... Sai qual è il modo migliore e più semplice per aggiornarli/aggiornarli? – user1106770

2

puoi semplicemente fare:

for key in mydict.keys(): 
    f.write(str(key) + ":" + str(mydict[key]) + ","); 

In modo che si può avere

chiave_1: valore_1, Pulsante 2: valore_2

+3

Better would be '','. join ("% s:% s "% (k, v) per k, v in mydict.items())' - di solito stai meglio iterando sugli elementi di dict, che ti danno le chiavi e valori insieme, rispetto alle chiavi di un dict e facendo ricerche di valore "n". '','. join (...)' si occupa solo di inserire virgole tra i valori, senza aggiungere la virgola finale extra. – PaulMcG

+0

grazie @PaulMcGuire –

1

ho personalmente sempre trovato il tipo di modulo csv fastidioso. Mi aspetto che qualcun altro vi mostrerà come fare questo slickly con esso, ma la mia soluzione rapida e sporca è:

with open('dict.csv', 'w') as f: # This creates the file object for the context 
            # below it and closes the file automatically 
    l = [] 
    for k, v in mydict.iteritems(): # Iterate over items returning key, value tuples 
     l.append('%s: %s' % (str(k), str(v))) # Build a nice list of strings 
    f.write(', '.join(l))      # Join that list of strings and write out 

Tuttavia, se si desidera leggere di nuovo in, avrete bisogno di fare un po 'di analisi irritante , soprattutto se è tutto su una riga. Ecco un esempio usando il tuo formato di file proposto.

with open('dict.csv', 'r') as f: # Again temporary file for reading 
    d = {} 
    l = f.read().split(',')  # Split using commas 
    for i in l: 
     values = i.split(': ') # Split using ': ' 
     d[values[0]] = values[1] # Any type conversion will need to happen here 
+0

Vorrei andare con la risposta di Ricardo. O almeno usare linee separate. –

3
outfile = open('dict.txt', 'w') 
for key, value in sorted(mydict.items()): 
    outfile.write(str(key) + '\t' + str(value) + '\n') 
+1

Fornisci inoltre alcune informazioni o commenti sulla tua risposta. – NDM

10

Il modo più semplice è quello di ignorare il modulo formato CSV e da soli.

with open('my_file.csv', 'w') as f: 
    [f.write('{0},{1}\n'.format(key, value)) for key, value in my_dict.items()] 
+4

Se il tuo 'chiave' ottiene una virgola, avrai un brutto momento. –

+2

Trovo più facile usare semplicemente 'csv.writer (...). Writows (my_dict.items())'. Il modulo 'csv' fa molto di più che aggiungere solo virgole e newline. –

2

Giusto per dare un'opzione, la scrittura di un dizionario nel file csv potrebbe anche essere eseguita con il pacchetto pandas. Con l'esempio dato che potrebbe essere qualcosa di simile:

mydict = {'key1': 'a', 'key2': 'b', 'key3': 'c'}

import pandas as pd 

(pd.DataFrame.from_dict(data=mydict, orient='index') 
    .to_csv('dict_file.csv', header=False)) 

La cosa principale da tenere in considerazione è quello di impostare il parametro 'oriente' a 'index' all'interno del metodo from_dict.Questo ti permette di scegliere se vuoi scrivere ogni chiave del dizionario in una nuova riga.

Inoltre, all'interno del metodo to_csv il parametro dell'intestazione è impostato su False solo per avere solo gli elementi del dizionario senza fastidiose righe. È sempre possibile impostare i nomi di colonne e indici all'interno del metodo to_csv.

L'output sarà simile a questa:

key1,a 
key2,b 
key3,c 

Se invece si desidera che i tasti siano i nomi della colonna, basta utilizzare il parametro di default 'orientare' che è 'colonne', come si potrebbe verificare nel collegamenti alla documentazione.

Problemi correlati