Lưu trữ từ điển Python


198

Tôi đã quen với việc đưa dữ liệu vào và ra khỏi Python bằng các tệp .csv, nhưng có những thách thức rõ ràng đối với việc này. Bạn có lời khuyên nào về những cách đơn giản để lưu trữ từ điển (hoặc bộ từ điển) trong tệp json hoặc pck không? Ví dụ:

data = {}
data ['key1'] = "keyinfo"
data ['key2'] = "keyinfo2"

Tôi muốn biết cả cách lưu cái này và sau đó làm thế nào để tải lại.


8
Bạn đã đọc tài liệu cho các mô-đun tiêu chuẩn json hoặc dưa chua ?
Greg Hewgill

Câu trả lời:


443

Lưu dưa chua :

try:
    import cPickle as pickle
except ImportError:  # python 3.x
    import pickle

with open('data.p', 'wb') as fp:
    pickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)

Xem tài liệu mô-đun dưa chua để biết thêm thông tin liên quan đến protocolđối số.

Tải dưa chua :

with open('data.p', 'rb') as fp:
    data = pickle.load(fp)

Lưu JSON :

import json

with open('data.json', 'w') as fp:
    json.dump(data, fp)

Cung cấp thêm đối số như sort_keyshoặc indentđể có được một kết quả đẹp. Đối số sort_keys sẽ sắp xếp các khóa theo thứ tự bảng chữ cái và thụt lề sẽ thụt vào cấu trúc dữ liệu của bạn bằng indent=Nkhoảng trắng.

json.dump(data, fp, sort_keys=True, indent=4)

Tải JSON :

with open('data.json', 'r') as fp:
    data = json.load(fp)

4
JSON thực hiện từ điển nguyên bản (mặc dù chúng rõ ràng không hoạt động chính xác như một từ điển python làm trong khi trong bộ nhớ, vì mục đích bền bỉ, chúng giống hệt nhau). Trong thực tế, đơn vị nền tảng trong json là "Đối tượng", được định nghĩa là {<chuỗi>: <value>}. Nhìn có quen không? Mô-đun json trong thư viện chuẩn hỗ trợ mọi kiểu gốc Python và có thể dễ dàng mở rộng với kiến ​​thức tối thiểu về json để hỗ trợ các lớp do người dùng định nghĩa. Trang chủ JSON hoàn toàn xác định ngôn ngữ chỉ trong hơn 3 trang in, do đó dễ dàng tiếp thu / tiêu hóa nhanh chóng.
Jonathanb

1
Cũng đáng để biết về đối số thứ ba pickle.dump, quá. Nếu tập tin không cần phải đọc được thì con người có thể tăng tốc mọi thứ lên rất nhiều.
Steve Jessop

11
Nếu bạn thêm sort_keys và đối số thụt lề vào lệnh gọi kết xuất, bạn sẽ nhận được kết quả đẹp hơn nhiều. ví dụ : json.dump(data, fp, sort_keys=True, indent=4). Thông tin thêm có thể được tìm thấy ở đây
juliusmh

1
Bạn có thể nên sử dụngpickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Martin Thoma

1
Đối với python 3, sử dụngimport pickle
nguy hiểm89

35

Ví dụ tối thiểu, viết trực tiếp vào một tệp:

import json
json.dump(data, open(filename, 'wb'))
data = json.load(open(filename))

hoặc đóng / mở an toàn:

import json
with open(filename, 'wb') as outfile:
    json.dump(data, outfile)
with open(filename) as infile:
    data = json.load(infile)

Nếu bạn muốn lưu nó trong một chuỗi thay vì một tệp:

import json
json_str = json.dumps(data)
data = json.loads(json_str)


5

Để ghi vào một tập tin:

import json
myfile.write(json.dumps(mydict))

Để đọc từ một tập tin:

import json
mydict = json.loads(myfile.read())

myfile là đối tượng tệp cho tệp mà bạn đã lưu dict trong.


Bạn đang kho mà json có lấy các tệp làm đối số và viết trực tiếp cho chúng không?

json.dump(myfile)json.load(myfile)
Niklas R

5

Nếu bạn sau khi tuần tự hóa nhưng sẽ không cần dữ liệu trong các chương trình khác, tôi thực sự khuyên bạn nên shelvemô-đun. Hãy nghĩ về nó như một cuốn từ điển dai dẳng.

myData = shelve.open('/path/to/file')

# check for values.
keyVar in myData

# set values
myData[anotherKey] = someValue

# save the data for future use.
myData.close()

2
Nếu bạn muốn lưu trữ toàn bộ một dict, hoặc tải toàn bộ một dict, jsonsẽ thuận tiện hơn. shelvechỉ tốt hơn để truy cập một khóa tại một thời điểm.
agf

3

Nếu bạn muốn một sự thay thế cho picklehoặc json, bạn có thể sử dụng klepto.

>>> init = {'y': 2, 'x': 1, 'z': 3}
>>> import klepto
>>> cache = klepto.archives.file_archive('memo', init, serialized=False)
>>> cache        
{'y': 2, 'x': 1, 'z': 3}
>>>
>>> # dump dictionary to the file 'memo.py'
>>> cache.dump() 
>>> 
>>> # import from 'memo.py'
>>> from memo import memo
>>> print memo
{'y': 2, 'x': 1, 'z': 3}

Với klepto, nếu bạn đã sử dụng serialized=True, từ điển sẽ được viết thành memo.pklmột từ điển ngâm thay vì với văn bản rõ ràng.

Bạn có thể truy cập kleptotại đây: https://github.com/uqfoundation/klepto

dillcó lẽ là một lựa chọn tốt hơn cho dưa chua pickle, vì nó dillcó thể tuần tự hóa hầu hết mọi thứ trong trăn. kleptocũng có thể sử dụng dill.

Bạn có thể truy cập dilltại đây: https://github.com/uqfoundation/dill

Mumbo-jumbo bổ sung trên một vài dòng đầu tiên là bởi vì kleptocó thể được cấu hình để lưu trữ từ điển vào một tệp, vào ngữ cảnh thư mục hoặc cơ sở dữ liệu SQL. API giống nhau cho bất cứ điều gì bạn chọn làm kho lưu trữ phụ trợ. Nó cung cấp cho bạn một từ điển "có thể lưu trữ " mà bạn có thể sử dụng loaddumptương tác với kho lưu trữ.


3

Đây là một chủ đề cũ, nhưng để hoàn thiện, chúng ta nên bao gồm ConfigParser và configparser, một phần của thư viện chuẩn trong Python 2 và 3, tương ứng. Mô-đun này đọc và ghi vào tệp cấu hình / ini và (ít nhất là trong Python 3) hoạt động theo nhiều cách như từ điển. Nó có thêm lợi ích là bạn có thể lưu trữ nhiều từ điển vào các phần riêng biệt của tệp config / ini và gọi lại chúng. Ngọt!

Ví dụ Python 2.7.x.

import ConfigParser

config = ConfigParser.ConfigParser()

dict1 = {'key1':'keyinfo', 'key2':'keyinfo2'}
dict2 = {'k1':'hot', 'k2':'cross', 'k3':'buns'}
dict3 = {'x':1, 'y':2, 'z':3}

# make each dictionary a separate section in config
config.add_section('dict1')
for key in dict1.keys():
    config.set('dict1', key, dict1[key])

config.add_section('dict2')
for key in dict2.keys():
    config.set('dict2', key, dict2[key])

config.add_section('dict3')
for key in dict3.keys():
    config.set('dict3', key, dict3[key])

# save config to file
f = open('config.ini', 'w')
config.write(f)
f.close()

# read config from file
config2 = ConfigParser.ConfigParser()
config2.read('config.ini')

dictA = {}
for item in config2.items('dict1'):
    dictA[item[0]] = item[1]

dictB = {}
for item in config2.items('dict2'):
    dictB[item[0]] = item[1]

dictC = {}
for item in config2.items('dict3'):
    dictC[item[0]] = item[1]

print(dictA)
print(dictB)
print(dictC)

Ví dụ Python 3.X.

import configparser

config = configparser.ConfigParser()

dict1 = {'key1':'keyinfo', 'key2':'keyinfo2'}
dict2 = {'k1':'hot', 'k2':'cross', 'k3':'buns'}
dict3 = {'x':1, 'y':2, 'z':3}

# make each dictionary a separate section in config
config['dict1'] = dict1
config['dict2'] = dict2
config['dict3'] = dict3

# save config to file
f = open('config.ini', 'w')
config.write(f)
f.close()

# read config from file
config2 = configparser.ConfigParser()
config2.read('config.ini')

# ConfigParser objects are a lot like dictionaries, but if you really
# want a dictionary you can ask it to convert a section to a dictionary
dictA = dict(config2['dict1'] )
dictB = dict(config2['dict2'] )
dictC = dict(config2['dict3'])

print(dictA)
print(dictB)
print(dictC)

đầu ra giao diện điều khiển

{'key2': 'keyinfo2', 'key1': 'keyinfo'}
{'k1': 'hot', 'k2': 'cross', 'k3': 'buns'}
{'z': '3', 'y': '2', 'x': '1'}

nội dung của config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

[dict2]
k1 = hot
k2 = cross
k3 = buns

[dict3]
z = 3
y = 2
x = 1

1

Nếu lưu vào tệp json, cách tốt nhất và dễ nhất để thực hiện việc này là:

import json
with open("file.json", "wb") as f:
    f.write(json.dumps(dict).encode("utf-8"))

Tại sao điều này dễ hơn json.dump( )là được nêu trong câu trả lời khác?
baxx

0

trường hợp sử dụng của tôi là lưu nhiều đối tượng json vào một tệp và câu trả lời của marty đã giúp tôi phần nào. Nhưng để phục vụ trường hợp sử dụng của tôi, câu trả lời không đầy đủ vì nó sẽ ghi đè lên dữ liệu cũ mỗi khi một mục nhập mới được lưu.

Để lưu nhiều mục trong một tệp, người ta phải kiểm tra nội dung cũ (tức là đọc trước khi viết). Một tệp thông thường chứa dữ liệu json sẽ có listhoặc là một objectgốc. Vì vậy, tôi đã cân nhắc rằng tệp json của tôi luôn có một list of objectsvà mỗi lần tôi thêm dữ liệu vào nó, tôi chỉ cần tải danh sách trước, nối dữ liệu mới của mình vào đó và đưa nó trở lại một thể hiện của tệp ( w):

def saveJson(url,sc): #this function writes the 2 values to file
    newdata = {'url':url,'sc':sc}
    json_path = "db/file.json"

    old_list= []
    with open(json_path) as myfile:  #read the contents first
        old_list = json.load(myfile)
    old_list.append(newdata)

    with open(json_path,"w") as myfile:  #overwrite the whole content
        json.dump(old_list,myfile,sort_keys=True,indent=4)

    return "sucess"

tệp json mới sẽ trông giống như thế này:

[
    {
        "sc": "a11",
        "url": "www.google.com"
    },
    {
        "sc": "a12",
        "url": "www.google.com"
    },
    {
        "sc": "a13",
        "url": "www.google.com"
    }
]

Chú ý: Đây là điều cần thiết để có một file có tên file.jsonvới []như dữ liệu ban đầu cho phương pháp này để làm việc

PS: không liên quan đến câu hỏi ban đầu, nhưng cách tiếp cận này cũng có thể được cải thiện hơn nữa bằng cách kiểm tra trước xem mục nhập của chúng tôi đã tồn tại chưa (dựa trên 1 / nhiều khóa) và chỉ sau đó nối thêm và lưu dữ liệu. Hãy cho tôi biết nếu ai đó cần kiểm tra, tôi sẽ thêm vào câu trả lời

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.