Запис словника у файл CSV з одним рядком для кожного 'ключ: значення'


90

У мене є словник:

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

Я хочу записати дані у файл dict.csv у такому стилі:

key1: value_a
key2: value_b
key3: value_c

Я написав:

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

Але тепер у мене всі ключі в одному рядку, а всі значення в наступному рядку ..

Коли мені вдається написати такий файл, я також хочу переглянути його у новий словник.

Просто для пояснення мого коду, словник містить значення та були з textctrls та прапорці (за допомогою wxpython). Я хочу додати кнопки "Зберегти налаштування" та "Завантажити налаштування". Параметри збереження повинні писати словник у файл згаданим способом (щоб полегшити користувачеві безпосереднє редагування файлу csv), параметри завантаження повинні читатись із файлу та оновлювати textctrls та прапорці.


1
Чи можете ви надати кращий приклад того, що ви хочете отримати як результат? "стиль" у вас вище не є CSV. ти шукаєш key1, value_a [linebreak] key2, value_b [linebreak] key3, value_c?
tkone

Інший підхід полягає у використанні repr()для виписування дикту, а потім виправлення рядка, коли ви його читаєте. Подивіться на цю стару публікацію SO, щоб обговорити str()проти repr(), а також документи .
Пітер Роуелл

Окрім моєї відповіді нижче, якщо ви віддаєте перевагу дещо вишуканішому, ніж простому CSV-файлу, можливо, ви захочете перевірити ConfigParserмодуль
Рікардо Карденес

3
Ви описуєте типовий формат CSV, виписаний модулем csv. Якщо ви виписуєте кілька диктів з однаковими клавішами, клавіші записуються лише один раз, у першому рядку, по одному рядку на дикт для відповідних значень, у належному порядку, щоб
збігатися

Відповіді:


185

Все DictWriterпрацює не так, як ви очікуєте.

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

Щоб прочитати це назад:

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

що є досить компактним, але передбачає, що вам не потрібно робити будь-яке перетворення типу під час читання


2
М-м-м-м ... Щойно помітили, що ви хочете отримати певний формат, який не зовсім схожий на CSV. Припустимо, що ви хочете стиль CSV (тобто рядок на пару ключ-значення), оскільки ви використовували модуль CSV ...
Рікардо Карденес

3
Або ... на випадок, якщо підхід CSV - це саме те, що ви хотіли, але ви віддаєте перевагу ":" як роздільник, просто додайте delimiter=':'при створенні автора і читача :)
Рікардо Карденес

2
Зверніть увагу, що слід закрити файл між написанням та читанням. Подивіться , що сталося в цьому питання / відповідь: stackoverflow.com/a/38467563/235698
Марк Tolonen

1
@MarkTolonen, звичайно, використання withбуло б краще. Я зміню приклади, щоб це відобразити ...
Рікардо Карденес

1
@DareYang вибачте за затримку. Насправді, я не впевнений, чому я написав його тоді. Це не потрібно. Під час запису ефект цього полягає в тому, що символи нового рядка залишаються неперекладеними (тобто, якщо ви пишете \n, ви потрапите \nу файл). Якщо залишитись наодинці, починається "універсальний режим", і нові рядки перекладаються за замовчуванням для поточної операційної системи. Враховуючи, що це насправді тут не корисно (крім випадків, коли ви хочете мати передбачувані нові рядки), я його видалю.
Рікардо Карденес

27

Просто щоб дати можливість, написання словника у файл csv також можна зробити за допомогою пакету pandas. У наведеному прикладі це може бути приблизно так:

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

Головне, що слід взяти до уваги, це встановити для параметра 'orient' значення 'index' усередині методу from_dict . Це дозволяє вибрати, чи потрібно писати кожен ключ словника в новому рядку.

Крім того, всередині методу to_csv для параметра заголовка встановлено значення False, щоб мати лише елементи словника без надокучливих рядків. Ви завжди можете встановити імена стовпців та індексів всередині методу to_csv.

Ваш результат буде виглядати так:

key1,a
key2,b
key3,c

Якщо замість цього ви хочете, щоб ключі були іменами стовпців, просто використовуйте параметр "орієнтація" за замовчуванням, який є "стовпці", як це можна було перевірити в посиланнях на документацію.


2
Відмінно працювало як шарм :). Моїм значенням був список, і він генерував мій csv із усіма значеннями списку в декількох клітинках і відображався на ключ у першому стовпці.
vinsinraw

14

Найпростіший спосіб - проігнорувати модуль csv та відформатувати його самостійно.

with open('my_file.csv', 'w') as f:
    [f.write('{0},{1}\n'.format(key, value)) for key, value in my_dict.items()]

8
Якщо ваша keyкоманда отримає кому, вам буде погано провести час.
Алі Ашраф,

5
Мені простіше просто використовувати csv.writer(...).writerows(my_dict.items()). csvМодуль робить це набагато більше , ніж просто додати коми і новий рядок.
Мартін Пітерс

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

1
Будь ласка, також надайте деяку інформацію або коментарі до своєї відповіді.
NDM

2

Чи можете ви просто зробити:

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

Щоб ви могли мати

ключ_1: значення_1, ключ_2: значення_2


3
Краще було б ','.join("%s:%s" % (k,v) for k,v in mydict.items())- вам, як правило, краще робити ітерацію над елементами дикту, що дає вам ключі та значення разом, ніж над ключами дикту та виконувати пошук n-значень. ','.join(...)дбає лише про те, щоб ставити коми між значеннями, не додаючи зайвої кінці завершення.
PaulMcG

зауважте, що для цього коду пітона вам не знадобиться крапка з комою в кінці
beep_check

1

Я особисто завжди вважав модуль csv набридливим. Я сподіваюся, хтось інший покаже вам, як це зробити з ним, але моє швидке і брудне рішення:

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

Однак, якщо ви хочете прочитати його ще раз, вам доведеться зробити дратівливий синтаксичний розбір, особливо якщо це все в одному рядку. Ось приклад використання запропонованого вами формату файлу.

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

введіть тут опис зображення


Я не думаю, що вам потрібно явно закривати файл у останньому рядку. Менеджер контексту робить це за вас.
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

Було б краще, якщо ви додасте невелике пояснення
Роаїм,

-2

Ви пробували додати "s" на: w.writerow(mydict)like this w.writerows(mydict):? Ця проблема трапилася зі мною, але зі списками я використовував однину замість множини.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.