Schreiben eines Wörterbuchs in eine CSV-Datei mit einer Zeile für jeden 'Schlüssel: Wert'

87

Ich habe ein Wörterbuch:

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

Ich möchte die Daten in diesem Stil in eine Datei dict.csv schreiben:

key1: value_a
key2: value_b
key3: value_c

Ich hab geschrieben:

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

Aber jetzt habe ich alle Schlüssel in einer Zeile und alle Werte in der nächsten Zeile.

Wenn ich es schaffe, eine solche Datei zu schreiben, möchte ich sie auch in ein neues Wörterbuch zurücklesen.

Um meinen Code zu erklären, enthält das Wörterbuch Werte und Bools aus Textctrls und Kontrollkästchen (mit wxpython). Ich möchte die Schaltflächen "Einstellungen speichern" und "Einstellungen laden" hinzufügen. Einstellungen speichern sollte das Wörterbuch auf die erwähnte Weise in die Datei schreiben (um dem Benutzer das direkte Bearbeiten der CSV-Datei zu erleichtern), Ladeeinstellungen sollten aus der Datei lesen und die Textelemente und Kontrollkästchen aktualisieren.

user1106770
quelle
1
Können Sie ein besseres Beispiel dafür liefern, was Sie als Ausgabe wünschen? Der "Stil", den Sie oben haben, ist nicht CSV. suchst key1, value_a [linebreak] key2, value_b [linebreak] key3, value_cdu
Tkone
Ein anderer Ansatz besteht darin repr(), das Diktat zu schreiben und die Zeichenfolge beim Einlesen zu bewerten. In diesem alten SO-Beitrag finden Sie eine Diskussion über str()vs. repr()und die Dokumente .
Peter Rowell
Abgesehen von meiner Antwort unten, wenn Sie etwas etwas anspruchsvolleres als nur eine einfache CSV-Datei bevorzugen, möchten Sie vielleicht das ConfigParserModul überprüfen
Ricardo Cárdenes
3
Was Sie beschreiben, ist das typische CSV-Format, das vom CSV-Modul geschrieben wurde. Wenn Sie mehrere Diktate mit denselben Schlüsseln schreiben, werden die Schlüssel nur einmal in der ersten Zeile mit einer Zeile pro Diktat für die entsprechenden Werte in der richtigen Reihenfolge geschrieben, um mit den Schlüsseln in Zeile 1
übereinzustimmen.

Antworten:

176

Das DictWriterfunktioniert nicht so, wie Sie es erwarten.

# For python 2, skip the "newline" argument: open('dict.csv','w")
with open('dict.csv', 'w') as csv_file:  
    writer = csv.writer(csv_file)
    for key, value in mydict.items():
       writer.writerow([key, value])

Um es zurückzulesen:

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

Das ist ziemlich kompakt, setzt aber voraus, dass Sie beim Lesen keine Typkonvertierung durchführen müssen

Ricardo Cárdenes
quelle
2
Mmh ... Ich habe gerade bemerkt, dass Sie ein bestimmtes Format wollten, das nicht genau CSV-ähnlich ist. Angenommen, Sie wollten einen CSV-Stil (dh eine Zeile pro Schlüssel-Wert-Paar), weil Sie das CSV-Modul verwendet haben ...
Ricardo Cárdenes
3
Oder ... falls der CSV-Ansatz genau das ist, was Sie wollten, Sie aber ":" als Trennzeichen bevorzugen, fügen Sie einfach hinzu, delimiter=':'wenn Sie den Autor und den Leser
erstellen
2
Beachten Sie, dass Sie die Datei zwischen Schreiben und Lesen schließen sollten. Sehen Sie, was in dieser Frage / Antwort passiert ist: stackoverflow.com/a/38467563/235698
Mark Tolonen
1
@ MarkTolonen sicherlich withwäre die Verwendung besser. Ich werde die Beispiele ändern, um es zu reflektieren ...
Ricardo Cárdenes
1
@DareYang Entschuldigung für die Verzögerung. Eigentlich bin ich mir nicht sicher, warum ich es damals geschrieben habe. Es wird nicht benötigt. Dies führt beim Schreiben dazu, dass Zeilenumbrüche nicht übersetzt werden (dh wenn Sie schreiben \n, gelangen Sie \nin die Datei). Wenn Sie dies alleine lassen, wird der "Universalmodus" aktiviert und die Zeilenumbrüche werden in die Standardeinstellung für das aktuelle Betriebssystem übersetzt. Da es hier nicht wirklich nützlich ist (außer wenn Sie vorhersehbare Zeilenumbrüche wünschen), werde ich es entfernen.
Ricardo Cárdenes
23

Nur um eine Option zu geben, könnte das Schreiben eines Wörterbuchs in eine CSV-Datei auch mit dem Pandas-Paket erfolgen. Mit dem gegebenen Beispiel könnte es ungefähr so ​​sein:

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

Die wichtigste zu berücksichtigende Sache ist, den Parameter 'orient' innerhalb der from_dict- Methode auf 'index' zu setzen . Auf diese Weise können Sie auswählen, ob Sie jeden Wörterbuchschlüssel in eine neue Zeile schreiben möchten.

Zusätzlich wird innerhalb der to_csv- Methode der Header-Parameter auf False gesetzt, um nur die Wörterbuchelemente ohne störende Zeilen zu haben. Sie können jederzeit Spalten- und Indexnamen innerhalb der to_csv-Methode festlegen.

Ihre Ausgabe würde folgendermaßen aussehen:

key1,a
key2,b
key3,c

Wenn Sie stattdessen möchten, dass die Schlüssel die Spaltennamen sind, verwenden Sie einfach den Standardparameter 'orient', der 'Spalten' ist, wie Sie in den Dokumentationslinks überprüfen können.

Ivan Calderon
quelle
1
Ausgezeichnet wie ein Zauber gearbeitet :). Mein Wert war eine Liste und er erzeugte meine CSV mit allen Listenwerten in mehreren Zellen und wurde dem Schlüssel in der ersten Spalte zugeordnet.
Vinsinraw
14

Am einfachsten ist es, das CSV-Modul zu ignorieren und selbst zu formatieren.

with open('my_file.csv', 'w') as f:
    [f.write('{0},{1}\n'.format(key, value)) for key, value in my_dict.items()]
Phil Horowitz
quelle
8
Wenn Sie keyein Komma bekommen, werden Sie eine schlechte Zeit haben.
Ali Ashraf
5
Ich finde es einfacher, nur zu benutzen csv.writer(...).writerows(my_dict.items()). Das csvModul kann so viel mehr als nur Kommas und Zeilenumbrüche hinzufügen.
Martijn Pieters
6
outfile = open( 'dict.txt', 'w' )
for key, value in sorted( mydict.items() ):
    outfile.write( str(key) + '\t' + str(value) + '\n' )
FCAlive
quelle
1
Bitte geben Sie auch einige Informationen oder Kommentare zu Ihrer Antwort an.
NDM
2

Können Sie einfach tun:

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

Damit du haben kannst

Schlüssel_1: Wert_1, Schlüssel_2: Wert_2

louis.luo
quelle
3
Besser wäre es ','.join("%s:%s" % (k,v) for k,v in mydict.items())- Sie sind normalerweise besser dran, über die Elemente eines Diktats zu iterieren, wodurch Sie Schlüssel und Werte zusammen erhalten, als über die Schlüssel eines Diktats und 'n' Wert-Lookups durchzuführen. ','.join(...)sorgt dafür, dass nur Kommas zwischen Werte gesetzt werden, ohne das zusätzliche nachfolgende Komma hinzuzufügen.
PaulMcG
Beachten Sie, dass Sie das Semikolon am Ende für diesen Python-Code nicht benötigen
beep_check
1

Ich persönlich fand das CSV-Modul immer etwas nervig. Ich gehe davon aus, dass Ihnen jemand anderes zeigen wird, wie man das geschickt macht, aber meine schnelle und schmutzige Lösung lautet:

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

Wenn Sie es jedoch wieder einlesen möchten, müssen Sie einige irritierende Analysen durchführen, insbesondere wenn alles in einer Zeile steht. Hier ist ein Beispiel mit Ihrem vorgeschlagenen Dateiformat.

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
Griffith Rees
quelle
Ich würde Ricardos Antwort folgen. Oder verwenden Sie zumindest separate Zeilen.
Griffith Rees
0
import csv

dict = {"Key Header":"Value Header", "key1":"value1", "key2":"value2"}

with open("test.csv", "w") as f:
    writer = csv.writer(f)
    for i in dict:
      writer.writerow([i, dict[i]])
f.close() 

Geben Sie hier die Bildbeschreibung ein

Apurva Thorat
quelle
Ich glaube nicht, dass Sie die Datei in der letzten Zeile explizit schließen müssen. Der Kontextmanager erledigt das für Sie.
avaj_wen12
0
#code to insert and read dictionary element from csv file
import csv
n=input("Enter I to insert or S to read : ")
if n=="I":
    m=int(input("Enter the number of data you want to insert: "))
    mydict={}
    list=[]
    for i in range(m):
        keys=int(input("Enter id :"))
        list.append(keys)
        values=input("Enter Name :")
        mydict[keys]=values

    with open('File1.csv',"w") as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=list)
        writer.writeheader()
        writer.writerow(mydict)
        print("Data Inserted")
else:
    keys=input("Enter Id to Search :")
    Id=str(keys)
    with open('File1.csv',"r") as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            print(row[Id]) #print(row) to display all data
Ashish Nandan
quelle
Es wäre besser, wenn Sie eine kleine Erklärung hinzufügen
Roaim
-2

Haben Sie versucht, das "s" hinzuzufügen: w.writerow(mydict)so : w.writerows(mydict)? Dieses Problem ist mir passiert, aber bei Listen habe ich Singular anstelle von Plural verwendet.

Hikhuj
quelle