2011-12-31 20 views
53

Tengo un diccionario:Python: Escribir un diccionario en un archivo CSV con una línea para cada 'clave: valor'

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

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

key1: value_a 
key2: value_b 
key3: value_c 

me escribió:

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 Valu es en la siguiente fila ...

Cuando logro escribir un archivo como este, también quiero 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 configuraciones" y "Cargar configuraciones". La configuración de guardar 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), cargar la configuración debe leer el archivo y actualizar los cuadros de texto y las casillas de verificación.

+1

¿Puede proporcionar un mejor ejemplo de lo que quiere como resultado? el "estilo" que tienes arriba no es CSV. ¿Estás buscando 'key1, value_a [linebreak] key2, value_b [linebreak] key3, value_c'? – tkone

+0

Otro enfoque es usar 'repr()' para escribir el dict y luego evaluar la cadena cuando lo lees. Mira esto [antigua publicación SO] (http://stackoverflow.com/questions/1436703/difference- between-str-and-repr-in-python) para una discusión de 'str()' vs. 'repr()', y [los documentos] (http://docs.python.org/library/functions.html #repr), también. –

+0

Además de mi respuesta a continuación, si prefieres algo un poco más sofisticado que un simple archivo CSV, es posible que desees consultar el módulo 'ConfigParser' –

Respuesta

121

El DictWriter no funciona de la forma esperada.

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

Para leer de nuevo:

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

que es bastante compacto, pero se supone que no tiene que hacer ningún tipo de conversión al leer

+1

Mmh ... Acabo de darme cuenta de que querías un formato específico que no sea exactamente como el CSV. Supuse que quería el estilo CSV (es decir, una fila por par clave-valor) porque estaba usando el módulo CSV ... –

+2

O ... en caso de que el enfoque CSV sea exactamente lo que quería, pero prefiere ":" como un separador, simplemente agregue 'delimiter = ':'' al crear el escritor y el lector :) –

+0

escribir y leer funciona bien ahora, pero también me gustaría actualizar mis casillas de verificación y textctrl según los valores de mi diccionario. Tengo todos mis widgets en "def create_controls", que se llama cuando inicio mi programa. Pero simplemente llamar de nuevo después de leer desde mi csv no actualiza el estado de mis widgets ... ¿Sabes cuál es la mejor y más simple forma de actualizarlos o actualizarlos? – user1106770

2

¿Puede usted acaba de hacer:

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

Así que usted puede tener

clave_1: valor_1, Pulsador 2: valor_2

+3

Mejor sería be '','. join ("% s:% s "% (k, v) para k, v en mydict.items())' - por lo general, es mejor iterar sobre los elementos de un dict, lo que le da claves y valores juntos, que sobre las claves de un dict y hacer búsquedas de valores 'n'. '','. join (...)' solo se encarga de poner comas entre los valores, sin agregar la coma adicional. – PaulMcG

+0

gracias @PaulMcGuire –

1

Yo personalmente siempre he encontrado el módulo csv tipo de molesto. Espero que alguien le mostrará cómo hacer esto hábilmente con ella, 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 quieres leerlo de nuevo, tendrá que hacer un poco de análisis irritante , especialmente si todo está en una línea. Aquí hay un ejemplo usando su 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 
+0

Me gustaría ir con la respuesta de Ricardo. O al menos use líneas separadas. –

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

También proporcione información o comentarios sobre su respuesta. – NDM

10

La manera más fácil es ignorar el módulo csv y dar formato a 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()] 
+4

Si tu 'clave' tiene una coma, vas a tener un mal momento. –

+2

Me resulta más fácil usar 'csv.writer (...). Writerows (my_dict.items())'. El módulo 'csv' hace mucho más que simplemente agregar comas y líneas nuevas. –

2

Sólo para dar una opción, escribir un diccionario de archivo csv también se podría hacer con el paquete de osos panda. Con el ejemplo dado que 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 fijar el parámetro 'Oriente' a 'índice' 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 del encabezado se establece en False solo para tener solo los elementos del diccionario sin filas molestas. Siempre puede establecer los nombres de columna e índice dentro del método to_csv.

Su salida se vería así:

key1,a 
key2,b 
key3,c 

Si por el contrario desea que las teclas sean nombres de la columna, sólo tiene que utilizar el parámetro por defecto 'orientar' que es 'columnas', como se puede comprobar en el enlaces de documentación.

Cuestiones relacionadas