Escrevendo um dicionário em um arquivo csv com uma linha para cada 'chave: valor'

88

Eu tenho um dicionário:

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

Quero gravar os dados em um arquivo dict.csv, neste estilo:

key1: value_a
key2: value_b
key3: value_c

Eu escrevi:

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

Mas agora tenho todas as chaves em uma linha e todos os valores na próxima linha.

Quando consigo escrever um arquivo como este, também quero lê-lo em um novo dicionário.

Apenas para explicar meu código, o dicionário contém valores e bools de textctrls e caixas de seleção (usando wxpython). Desejo adicionar os botões "Salvar configurações" e "Carregar configurações". Salvar configurações deve gravar o dicionário no arquivo da maneira mencionada (para tornar mais fácil para o usuário editar o arquivo csv diretamente), carregar as configurações deve ler do arquivo e atualizar os textctrls e caixas de seleção.

user1106770
fonte
1
você pode fornecer um exemplo melhor do que deseja como saída? o "estilo" que você tem acima não é CSV. você está procurando key1, value_a [linebreak] key2, value_b [linebreak] key3, value_c?
tkone
Outra abordagem é usar repr()para escrever o ditado e, em seguida, avaliar a string ao lê-lo. Veja este post antigo do SO para ver as discussões sobre o str()verso repr()e os documentos também.
Peter Rowell
Além da minha resposta abaixo, se você prefere algo um pouco mais sofisticado do que apenas um arquivo CSV simples, você pode querer verificar o ConfigParsermódulo
Ricardo Cárdenes
3
O que você descreve é ​​o formato CSV típico escrito pelo módulo csv. Se você escrever vários dicts com as mesmas chaves, as chaves são escritas apenas uma vez, na primeira linha, com uma linha por dict para os valores correspondentes, na ordem adequada para alinhar com as chaves na linha 1.
PaulMcG

Respostas:

181

O DictWriternão funciona da maneira que você espera.

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

Para ler de volta:

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

que é bastante compacto, mas assume que você não precisa fazer nenhuma conversão de tipo ao ler

Ricardo Cárdenes
fonte
2
Mmh ... Acabei de notar que você queria um formato específico que não seja exatamente como CSV. Presume-se que você deseja um estilo CSV (ou seja, uma linha por par de valores-chave) porque está usando o módulo CSV ...
Ricardo Cárdenes
3
Ou ... caso a abordagem CSV seja exatamente o que você queria, mas você prefere ":" como separador, basta adicionar delimiter=':'ao criar o escritor e o leitor :)
Ricardo Cárdenes
2
Observe que você deve fechar o arquivo entre a gravação e a leitura. Veja o que aconteceu nesta pergunta / resposta: stackoverflow.com/a/38467563/235698
Mark Tolonen
1
@MarkTolonen certamente, usar withseria melhor. Vou mudar os exemplos para refletir isso ...
Ricardo Cárdenes
1
@DareYang desculpe pelo atraso. Na verdade, não sei por que o escrevi naquela época. Não é necessário. Ao escrever, o efeito disso é deixar os caracteres de nova linha não traduzidos (ou seja, se você escrever \n, receberá \no arquivo). Se deixado sozinho, o "modo universal" entra em ação e as novas linhas são traduzidas para o padrão do sistema operacional atual. Dado que não é realmente útil aqui (exceto se você quiser ter novas linhas previsíveis), vou removê-lo.
Ricardo Cárdenes
26

Apenas para dar uma opção, escrever um dicionário em um arquivo csv também pode ser feito com o pacote pandas. Com o exemplo fornecido, poderia ser algo assim:

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

A principal coisa a levar em consideração é definir o parâmetro 'orient' como 'index' dentro do método from_dict . Isso permite que você escolha se deseja escrever cada chave do dicionário em uma nova linha.

Além disso, dentro do método to_csv , o parâmetro header é definido como False apenas para ter apenas os elementos de dicionário sem linhas irritantes. Você sempre pode definir nomes de coluna e índice dentro do método to_csv.

Sua saída ficaria assim:

key1,a
key2,b
key3,c

Se ao invés disso você quiser que as chaves sejam os nomes das colunas, apenas use o parâmetro padrão 'orientar' que é 'colunas', como você pode verificar nos links da documentação.

Ivan Calderon
fonte
1
Excelente funcionou como um encanto :). Meu valor era uma lista e gerou meu csv com todos os valores da lista em várias células e mapeado para a chave na primeira coluna.
vinsinraw
14

A maneira mais fácil é ignorar o módulo csv e formatá-lo você mesmo.

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
fonte
8
Se keyreceber uma vírgula, você vai se divertir muito.
Ali Ashraf,
5
Acho mais fácil de usar csv.writer(...).writerows(my_dict.items()). O csvmódulo faz muito mais do que apenas adicionar vírgulas e novas linhas.
Martijn Pieters
6
outfile = open( 'dict.txt', 'w' )
for key, value in sorted( mydict.items() ):
    outfile.write( str(key) + '\t' + str(value) + '\n' )
FCAlive
fonte
1
Forneça também algumas informações ou comentários sobre sua resposta.
NDM de
2

Você pode apenas fazer:

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

Para que você possa ter

key_1: value_1, key_2: value_2

louis.luo
fonte
3
Melhor seria ','.join("%s:%s" % (k,v) for k,v in mydict.items())- geralmente é melhor iterar sobre os itens de um dicionário, que fornece chaves e valores juntos, do que sobre as chaves de um dicionário e fazer pesquisas de 'n' valor. ','.join(...)toma o cuidado de colocar apenas vírgulas entre os valores, sem adicionar a vírgula final extra.
PaulMcG
observe que você não precisará do ponto-e-vírgula no final para este código python
beep_check
1

Eu pessoalmente sempre achei o módulo csv um tanto chato. Espero que outra pessoa mostre como fazer isso habilmente com ele, mas minha solução rápida e suja é:

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

No entanto, se você quiser ler de volta, você precisará fazer algumas análises irritantes, especialmente se estiver tudo em uma linha. Aqui está um exemplo usando seu formato de arquivo 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
Griffith Rees
fonte
Eu iria com a resposta de Ricardo. Ou pelo menos use linhas 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() 

insira a descrição da imagem aqui

Apurva Thorat
fonte
Não acho que você precise fechar explicitamente o arquivo na última linha. O gerenciador de contexto faz isso por você.
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
fonte
Seria melhor se você adicionar uma pequena explicação
Roaim
-2

Você tentou adicionar o "s" em: w.writerow(mydict)assim w.writerows(mydict):? Esse problema aconteceu comigo, mas com listas, eu estava usando o singular em vez do plural.

Hikhuj
fonte