Ecrire un dictionnaire dans un fichier csv avec une ligne pour chaque 'clé: valeur'

92

J'ai un dictionnaire:

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

Je veux écrire les données dans un fichier dict.csv, dans ce style:

key1: value_a
key2: value_b
key3: value_c

J'ai écrit:

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

Mais maintenant, j'ai toutes les clés sur une ligne et toutes les valeurs sur la ligne suivante.

Quand j'arrive à écrire un fichier comme celui-ci, je veux aussi le relire dans un nouveau dictionnaire.

Juste pour expliquer mon code, le dictionnaire contient des valeurs et des booléens de textctrls et de cases à cocher (en utilisant wxpython). Je souhaite ajouter les boutons "Enregistrer les paramètres" et "Charger les paramètres". Les paramètres de sauvegarde doivent écrire le dictionnaire dans le fichier de la manière mentionnée (pour faciliter la modification directe du fichier csv par l'utilisateur), les paramètres de chargement doivent lire le fichier et mettre à jour les textctrls et les cases à cocher.

user1106770
la source
1
pouvez-vous donner un meilleur exemple de ce que vous voulez en sortie? le "style" que vous avez ci-dessus n'est pas CSV. cherchez-vous key1, value_a [linebreak] key2, value_b [linebreak] key3, value_c?
tkone
Une autre approche consiste à utiliser repr()pour écrire le dict et ensuite évaluer la chaîne lorsque vous la lisez. Regardez cet ancien message SO pour une discussion de str()vs. repr(), et les documents , aussi.
Peter Rowell
En dehors de ma réponse ci-dessous, si vous préférez quelque chose d'un peu plus sophistiqué qu'un simple fichier CSV, vous voudrez peut-être vérifier le ConfigParsermodule
Ricardo Cárdenes
3
Ce que vous décrivez est le format CSV typique écrit par le module csv. Si vous écrivez plusieurs dictés avec les mêmes clés, les clés sont écrites une seule fois, dans la première ligne, avec une ligne par dict pour les valeurs correspondantes, dans le bon ordre pour s'aligner avec les clés de la ligne 1.
PaulMcG

Réponses:

186

Le DictWriterne fonctionne pas comme vous le souhaitez.

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

Pour le relire:

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

ce qui est assez compact, mais cela suppose que vous n'avez pas besoin de faire de conversion de type lors de la lecture

Ricardo Cárdenes
la source
2
Mmh ... Je viens de remarquer que vous vouliez un format spécifique qui ne ressemble pas exactement au CSV. Supposons que vous vouliez un style CSV (c'est-à-dire une ligne par paire clé-valeur) parce que vous utilisiez le module CSV ...
Ricardo Cárdenes
3
Ou ... dans le cas où l'approche CSV est exactement ce que vous vouliez, mais que vous préférez ":" comme séparateur, ajoutez simplement delimiter=':'lors de la création de l'écrivain et du lecteur :)
Ricardo Cárdenes
2
Notez que vous devez fermer le fichier entre l'écriture et la lecture. Voyez ce qui s'est passé dans cette question / réponse: stackoverflow.com/a/38467563/235698
Mark Tolonen
1
@MarkTolonen certainement, utiliser withserait mieux. Je vais changer les exemples pour le refléter ...
Ricardo Cárdenes
1
@DareYang désolé pour le retard. En fait, je ne sais pas pourquoi je l'ai écrit à l'époque. Ce n'est pas nécessaire. Lors de l'écriture, cela a pour effet de laisser les caractères de nouvelle ligne non traduits (c'est-à-dire que si vous écrivez \n, vous entrerez \ndans le fichier). S'il est laissé seul, le "mode universel" entre en jeu et les nouvelles lignes sont traduites par défaut pour le système d'exploitation actuel. Étant donné que ce n'est pas vraiment utile ici (sauf si vous voulez avoir des nouvelles lignes prévisibles), je vais le supprimer.
Ricardo Cárdenes le
27

Juste pour donner une option, écrire un dictionnaire dans un fichier csv pourrait également être fait avec le paquet pandas. Avec l'exemple donné, cela pourrait être quelque chose comme ceci:

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 principale chose à prendre en compte est de définir le paramètre «orient» sur «index» dans la méthode from_dict . Cela vous permet de choisir si vous souhaitez écrire chaque clé de dictionnaire dans une nouvelle ligne.

De plus, dans la méthode to_csv , le paramètre d'en-tête est défini sur False juste pour n'avoir que les éléments du dictionnaire sans lignes ennuyeuses. Vous pouvez toujours définir les noms de colonne et d'index dans la méthode to_csv.

Votre sortie ressemblerait à ceci:

key1,a
key2,b
key3,c

Si à la place vous voulez que les clés soient les noms des colonnes, utilisez simplement le paramètre par défaut «orient» qui est «colonnes», comme vous pouvez vérifier les liens de documentation.

Ivan Calderon
la source
2
Excellent a fonctionné comme un charme :). Ma valeur était une liste et elle a généré mon csv avec toutes les valeurs de liste dans plusieurs cellules et mappé à la clé dans la première colonne.
vinsinraw
14

Le moyen le plus simple est d'ignorer le module csv et de le formater vous-même.

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
la source
8
Si vous avez keyune virgule, vous allez passer un mauvais moment.
Ali Ashraf
5
Je trouve que c'est plus facile à utiliser csv.writer(...).writerows(my_dict.items()). Le csvmodule fait bien plus que simplement ajouter des virgules et des retours à la ligne.
Martijn Pieters
6
outfile = open( 'dict.txt', 'w' )
for key, value in sorted( mydict.items() ):
    outfile.write( str(key) + '\t' + str(value) + '\n' )
FCAlive
la source
1
Veuillez également fournir des informations ou des commentaires sur votre réponse.
NDM
2

Pouvez-vous simplement faire:

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

Pour que vous puissiez avoir

clé_1: valeur_1, clé_2: valeur_2

louis.luo
la source
3
Mieux serait ','.join("%s:%s" % (k,v) for k,v in mydict.items())- vous feriez généralement mieux d'itérer sur les éléments d'un dict, ce qui vous donne les clés et les valeurs ensemble, que sur les clés d'un dict et de faire des recherches de valeurs «n». ','.join(...)prend soin de ne mettre que des virgules entre les valeurs, sans ajouter la virgule de fin supplémentaire.
PaulMcG
notez que vous n'aurez pas besoin du point-virgule à la fin pour ce code python
beep_check
1

Personnellement, j'ai toujours trouvé le module csv assez ennuyeux. Je m'attends à ce que quelqu'un d'autre vous montre comment faire cela avec brio, mais ma solution rapide et sale est:

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

Cependant, si vous voulez le relire, vous devrez effectuer une analyse irritante, surtout si tout est sur une seule ligne. Voici un exemple utilisant le format de fichier proposé.

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
la source
J'irais avec la réponse de Ricardo. Ou au moins, utilisez des lignes séparées.
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() 

entrez la description de l'image ici

Apurva Thorat
la source
Je ne pense pas que vous deviez fermer explicitement le fichier dans la dernière ligne. Le gestionnaire de contexte fait cela pour vous.
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
la source
Ce serait mieux si vous ajoutez une petite explication
Roaim
-2

Avez-vous essayé d'ajouter le "s" sur: w.writerow(mydict)comme ceci w.writerows(mydict):? Ce problème m'est arrivé mais avec les listes, j'utilisais le singulier au lieu du pluriel.

Hikhuj
la source