Ghi từ điển vào tệp csv với một dòng cho mỗi 'key: value'


91

Tôi có một từ điển:

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

Tôi muốn ghi dữ liệu vào tệp dict.csv, theo kiểu sau:

key1: value_a
key2: value_b
key3: value_c

Tôi đã viết:

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

Nhưng bây giờ tôi có tất cả các khóa trong một hàng và tất cả các giá trị trong hàng tiếp theo ..

Khi tôi quản lý để viết một tệp như thế này, tôi cũng muốn đọc nó trở lại từ điển mới.

Chỉ để giải thích mã của tôi, từ điển chứa các giá trị và bools từ các textctrl và hộp kiểm (sử dụng wxpython). Tôi muốn thêm nút "Lưu cài đặt" và "Tải cài đặt". Lưu cài đặt nên ghi từ điển vào tệp theo cách đã đề cập (để giúp người dùng chỉnh sửa tệp csv trực tiếp dễ dàng hơn), cài đặt tải nên đọc từ tệp và cập nhật các textctrl và hộp kiểm.


1
bạn có thể cung cấp một ví dụ tốt hơn về những gì bạn muốn làm đầu ra không? "kiểu" bạn có ở trên không phải là CSV. bạn đang tìm kiếm key1, value_a [linebreak] key2, value_b [linebreak] key3, value_c?
tkone

Một cách tiếp cận khác là sử dụng repr()để viết chính tả ra và sau đó đánh giá chuỗi khi bạn đọc nó. Hãy xem bài đăng SO cũ này để biết các cuộc thảo luận về str()vs. repr()cả tài liệu nữa.
Peter Rowell,

Ngoài câu trả lời của tôi dưới đây, nếu bạn thích một chút gì đó phức tạp hơn chỉ là một tập tin CSV đơn giản, bạn có thể muốn kiểm tra các ConfigParsermô-đun
Ricardo Cárdenes

3
Những gì bạn mô tả là định dạng CSV điển hình do mô-đun csv viết ra. Nếu bạn viết ra nhiều ô với cùng một khóa, các khóa chỉ được viết một lần, ở dòng đầu tiên, với một dòng trên mỗi mệnh lệnh cho các giá trị tương ứng, theo thứ tự thích hợp để xếp hàng với các khóa ở dòng 1.
PaulMcG

Câu trả lời:


185

DictWriterkhông hoạt động theo cách bạn mong đợi.

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

Để đọc lại:

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

khá nhỏ gọn, nhưng nó giả định rằng bạn không cần thực hiện bất kỳ chuyển đổi kiểu nào khi đọc


2
Mmh ... Chỉ cần nhận thấy rằng bạn muốn một định dạng cụ thể không giống CSV chính xác. Giả sử rằng bạn muốn phong cách CSV (tức là một hàng cho mỗi cặp khóa-giá trị.) Vì bạn đang sử dụng các mô-đun CSV ...
Ricardo Cárdenes

3
Hoặc ... trong trường hợp các phương pháp CSV là chính xác những gì bạn muốn, nhưng bạn thích ":" như một dấu phân cách, chỉ cần thêm delimiter=':'khi tạo nhà văn và người đọc :)
Ricardo Cárdenes

2
Lưu ý, bạn nên đóng tệp giữa việc ghi và đọc. Hãy xem những gì đã xảy ra trong câu hỏi này / câu trả lời: stackoverflow.com/a/38467563/235698
Đánh dấu Tolonen

1
@MarkTolonen chắc chắn, sử dụng withsẽ tốt hơn. Tôi sẽ thay đổi các ví dụ để phản ánh nó ...
Ricardo Cárdenes

1
@DareYang xin lỗi vì sự chậm trễ. Thực ra, tôi không rõ tại sao mình lại viết nó hồi đó. Nó không cần thiết. Khi viết, tác dụng của việc này là để lại các ký tự dòng mới không được dịch (tức là nếu bạn viết \n, bạn sẽ nhận được \ntrong tệp). Nếu để một mình, "chế độ phổ thông" sẽ hoạt động và các dòng mới sẽ được dịch thành mặc định cho hệ điều hành hiện tại. Vì nó không thực sự hữu ích ở đây (ngoại trừ nếu bạn muốn có những dòng mới có thể dự đoán được), tôi sẽ xóa nó.
Ricardo Cárdenes

27

Chỉ để đưa ra một tùy chọn, việc ghi từ điển vào tệp csv cũng có thể được thực hiện với gói pandas. Với ví dụ đã cho, nó có thể là một cái gì đó như thế này:

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

Điều chính cần lưu ý là đặt tham số 'orient' thành 'index' bên trong phương thức from_dict . Điều này cho phép bạn chọn nếu bạn muốn viết mỗi khóa từ điển vào một hàng mới.

Thêm vào đó, bên trong phương thức to_csv , tham số tiêu đề được đặt thành Sai chỉ để chỉ có các phần tử từ điển không có các hàng gây khó chịu. Bạn luôn có thể đặt tên cột và chỉ mục bên trong phương thức to_csv.

Đầu ra của bạn sẽ giống như sau:

key1,a
key2,b
key3,c

Thay vào đó, nếu bạn muốn các khóa là tên của cột, chỉ cần sử dụng tham số 'định hướng' mặc định là 'cột', như bạn có thể kiểm tra trong các liên kết tài liệu.


2
Làm việc xuất sắc như một cái duyên :). Giá trị của tôi là một danh sách và nó đã tạo csv của tôi với tất cả các giá trị danh sách trong nhiều ô và được ánh xạ tới khóa trong cột đầu tiên.
vinsinraw 14/02/19

14

Cách dễ nhất là bỏ qua mô-đun csv và tự định dạng nó.

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

8
Nếu bạn keynhận được dấu phẩy, bạn sẽ có một khoảng thời gian tồi tệ.
Ali Ashraf

5
Tôi thấy nó dễ dàng hơn để sử dụng csv.writer(...).writerows(my_dict.items()). Các csvmô-đun không quá nhiều hơn chỉ cần thêm dấu phẩy và dòng mới.
Martijn Pieters

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

1
Vui lòng cung cấp một số thông tin hoặc nhận xét về câu trả lời của bạn.
NDM

2

Bạn chỉ cần làm:

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

Vì vậy, bạn có thể có

key_1: value_1, key_2: value_2


3
Sẽ tốt hơn ','.join("%s:%s" % (k,v) for k,v in mydict.items())- bạn thường nên lặp lại các mục của dict, điều này cung cấp cho bạn các khóa và giá trị cùng nhau, hơn là qua các khóa của dict và thực hiện tra cứu giá trị 'n'. ','.join(...)chỉ đặt dấu phẩy giữa các giá trị mà không thêm dấu phẩy ở cuối.
PaulMcG,

lưu ý rằng bạn sẽ không cần dấu chấm phẩy ở cuối cho mã python này
beep_check

1

Cá nhân tôi luôn thấy mô-đun csv là loại khó chịu. Tôi hy vọng ai đó sẽ chỉ cho bạn cách thực hiện điều này một cách khéo léo với nó, nhưng giải pháp nhanh chóng và bẩn thỉu của tôi là:

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

Tuy nhiên, nếu bạn muốn đọc lại nó, bạn sẽ cần phải thực hiện một số phân tích cú pháp khó chịu, đặc biệt nếu tất cả trên một dòng. Đây là một ví dụ sử dụng định dạng tệp được đề xuất của bạn.

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

Tôi sẽ đi với câu trả lời của Ricardo. Hoặc ít nhất là sử dụng các dòng riêng biệt.
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() 

nhập mô tả hình ảnh ở đây


Tôi không nghĩ rằng bạn cần phải đóng tệp một cách rõ ràng ở dòng cuối cùng. Trình quản lý ngữ cảnh thực hiện điều đó cho bạn.
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

Sẽ tốt hơn nếu bạn thêm một chút giải thích
Roaim

-2

Bạn đã thử thêm "s" vào: w.writerow(mydict)như thế này w.writerows(mydict):? Vấn đề này đã xảy ra với tôi nhưng với danh sách, tôi đang sử dụng số ít thay vì số nhiều.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.