Escribir un diccionario en un archivo csv con una línea por cada 'clave: valor'

92

Tengo un diccionario:

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

Quiero escribir los datos en un archivo dict.csv, en este estilo:

key1: value_a
key2: value_b
key3: value_c

Escribí:

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

Pero ahora tengo todas las claves en una fila y todos los valores en la siguiente fila.

Cuando consigo escribir un archivo como este, también quiero volver a leerlo en un nuevo diccionario.

Solo para explicar mi código, el diccionario contiene valores y bools de textctrls y casillas de verificación (usando wxpython). Quiero agregar los botones "Guardar configuración" y "Cargar configuración". Guardar configuración debe escribir el diccionario en el archivo de la manera mencionada (para que sea más fácil para el usuario editar el archivo csv directamente), la configuración de carga debe leer desde el archivo y actualizar las textctrls y las casillas de verificación.

usuario1106770
fuente
1
¿Puede proporcionar un mejor ejemplo de lo que desea como resultado? el "estilo" que tiene arriba no es CSV. está buscando key1, value_a [linebreak] key2, value_b [linebreak] key3, value_c?
tkone
Otro enfoque es usar repr()para escribir el dict y luego evaluar la cadena cuando lo lea. Mire esta vieja publicación de SO para una discusión de str()vs. repr(), y los documentos también.
Peter Rowell
Aparte de mi respuesta a continuación, si prefiere algo un poco más sofisticado que un simple archivo CSV, es posible que desee consultar el ConfigParsermódulo
Ricardo Cárdenes
3
Lo que describe es el formato CSV típico escrito por el módulo csv. Si escribe varios dictados con las mismas claves, las claves se escriben solo una vez, en la primera línea, con una línea por dictado para los valores correspondientes, en el orden correcto para alinearse con las claves en la línea 1.
PaulMcG

Respuestas:

186

El DictWriterno funciona de la forma esperada.

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

Para volver a leerlo:

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

que es bastante compacto, pero asume que no necesitas hacer ninguna conversión de tipo al leer

Ricardo Cárdenes
fuente
2
Mmh ... Acabo de notar que querías un formato específico que no es exactamente como CSV. Supuso que deseaba el estilo CSV (es decir, una fila por par clave-valor) porque estaba utilizando el módulo CSV ...
Ricardo Cárdenes
3
O ... en caso de que el enfoque CSV sea exactamente lo que deseaba, pero prefiere ":" como separador, simplemente agregue delimiter=':'al crear el escritor y el lector :)
Ricardo Cárdenes
2
Tenga en cuenta que debe cerrar el archivo entre escritura y lectura. Vea lo que sucedió en esta pregunta / respuesta: stackoverflow.com/a/38467563/235698
Mark Tolonen
1
@MarkTolonen ciertamente, usarlo withsería mejor. Cambiaré los ejemplos para reflejarlo ...
Ricardo Cárdenes
1
@DareYang perdón por el retraso. En realidad, no estoy seguro de por qué lo escribí en ese entonces. No es necesario. Al escribir, el efecto de esto es dejar los caracteres de nueva línea sin traducir (es decir, si escribe \n, entrará \nen el archivo). Si se deja solo, el "modo universal" se activa y las nuevas líneas se traducen al valor predeterminado para el sistema operativo actual. Dado que no es realmente útil aquí (excepto si desea tener nuevas líneas predecibles), lo eliminaré.
Ricardo Cárdenes
27

Solo para dar una opción, también se puede escribir un diccionario en un archivo csv con el paquete pandas. Con el ejemplo dado, podría ser algo como esto:

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

Lo principal a tener en cuenta es establecer el parámetro 'orient' en 'index' dentro del método from_dict . Esto le permite elegir si desea escribir cada clave del diccionario en una nueva fila.

Además, dentro del método to_csv , el parámetro de encabezado se establece en False solo para tener solo los elementos del diccionario sin filas molestas. Siempre puede establecer nombres de columnas e índices dentro del método to_csv.

Su salida se vería así:

key1,a
key2,b
key3,c

Si, en cambio, desea que las claves sean los nombres de las columnas, simplemente use el parámetro predeterminado 'orientar' que es 'columnas', como puede verificar en los enlaces de la documentación.

Iván Calderón
fuente
2
Excelente trabajado como un encanto :). Mi valor era una lista y generó mi csv con todos los valores de la lista en varias celdas y se asignó a la clave en la primera columna.
vinsinraw
14

La forma más sencilla es ignorar el módulo csv y formatearlo usted mismo.

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
fuente
8
Si keyobtiene una coma, lo pasará mal.
Ali Ashraf
5
Me resulta más fácil de usar csv.writer(...).writerows(my_dict.items()). El csvmódulo hace mucho más que simplemente agregar comas y nuevas líneas.
Martijn Pieters
6
outfile = open( 'dict.txt', 'w' )
for key, value in sorted( mydict.items() ):
    outfile.write( str(key) + '\t' + str(value) + '\n' )
FCAlive
fuente
1
Proporcione también información o comentarios sobre su respuesta.
NDM
2

Puedes simplemente hacer:

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

Para que puedas tener

clave_1: valor_1, clave_2: valor_2

louis.luo
fuente
3
Mejor sería ','.join("%s:%s" % (k,v) for k,v in mydict.items()): por lo general, es mejor iterar sobre los elementos de un dictado, que le brinda claves y valores juntos, que sobre las claves de un dictado y haciendo búsquedas de 'n' valores. ','.join(...)se encarga de poner solo comas entre los valores, sin agregar la coma final adicional.
PaulMcG
tenga en cuenta que no necesitará el punto y coma al final para este código de Python
beep_check
1

Personalmente, siempre he encontrado el módulo csv un poco molesto. Espero que alguien más le muestre cómo hacer esto hábilmente con él, pero mi solución rápida y sucia es:

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

Sin embargo, si desea volver a leerlo, deberá realizar un análisis irritante, especialmente si está todo en una sola línea. Aquí tienes un ejemplo con el formato de archivo propuesto.

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
fuente
Yo iría con la respuesta de Ricardo. O al menos use líneas separadas.
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() 

ingrese la descripción de la imagen aquí

Apurva Thorat
fuente
No creo que necesite cerrar explícitamente el archivo en la última línea. El administrador de contexto lo hace por usted.
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
fuente
Sería mejor si agrega una pequeña explicación
Roaim
-2

¿Ha intentado agregar la "s" en: w.writerow(mydict)así w.writerows(mydict):? Este problema me sucedió, pero con las listas, estaba usando singular en lugar de plural.

Hikhuj
fuente