การจัดเก็บพจนานุกรม Python


198

ฉันคุ้นเคยกับการนำข้อมูลเข้าและออกจาก Python โดยใช้ไฟล์. csv แต่มีความท้าทายที่ชัดเจนในเรื่องนี้ คำแนะนำเกี่ยวกับวิธีการง่ายๆในการจัดเก็บพจนานุกรม (หรือชุดพจนานุกรม) ในไฟล์ json หรือ pck? ตัวอย่างเช่น:

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

ฉันต้องการทราบทั้งวิธีการบันทึกและวิธีโหลดกลับ


8
คุณอ่านเอกสารสำหรับโมดูลjsonหรือpickleมาตรฐานแล้วหรือยัง?
เกร็กฮิวกิลล์

คำตอบ:


444

บันทึกดอง :

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)

ดูเอกสารประกอบของโมดูลดองสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการprotocolโต้แย้ง

โหลดดอง :

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

บันทึกJSON :

import json

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

ระบุอาร์กิวเมนต์พิเศษเช่นsort_keysหรือindentเพื่อให้ได้ผลลัพธ์ที่ดี อาร์กิวเมนต์sort_keysจะเรียงลำดับคีย์ตามตัวอักษรและเยื้องจะเยื้องโครงสร้างข้อมูลของคุณด้วยindent=Nช่องว่าง

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

โหลดJSON :

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

4
JSON ทำพจนานุกรมโดยกำเนิด (แม้ว่าพวกเขาจะไม่ได้ทำงานเหมือนที่พจนานุกรมงูใหญ่ทำในขณะที่อยู่ในหน่วยความจำเพื่อจุดประสงค์ในการติดตา ในความเป็นจริงหน่วยพื้นฐานใน json คือ "วัตถุ" ซึ่งถูกกำหนดเป็น {<string>: <value>} ดูคุ้นเคยไหม โมดูล json ในไลบรารีมาตรฐานรองรับทุกประเภทของภาษาไพ ธ อนและสามารถขยายได้อย่างง่ายดายด้วยความรู้ขั้นต่ำของ json เพื่อสนับสนุนคลาสที่ผู้ใช้กำหนดเอง หน้าแรกของ JSONกำหนดภาษาอย่างสมบูรณ์ในหน้าที่พิมพ์เพียง 3 หน้าดังนั้นจึงง่ายต่อการดูดซับ / แยกย่อยอย่างรวดเร็ว
Jonathanb

1
มันก็คุ้มค่าที่ได้รู้เกี่ยวกับข้อโต้แย้งที่สามpickle.dumpเช่นกัน หากไฟล์นั้นไม่จำเป็นต้องเป็นไฟล์ที่มนุษย์สามารถอ่านได้มันก็สามารถเร่งความเร็วได้มากขึ้น
Steve Jessop

11
หากคุณเพิ่มsort_keysและการเยื้องอาร์กิวเมนต์ในการเรียกการถ่ายโอนข้อมูลคุณจะได้ผลลัพธ์ที่ดีกว่ามาก json.dump(data, fp, sort_keys=True, indent=4)เช่น: ข้อมูลเพิ่มเติมสามารถดูได้ ที่นี่
juliusmh

1
คุณควรใช้pickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Martin Thoma

1
สำหรับ python 3 ให้ใช้import pickle
อันตราย 89

35

ตัวอย่างน้อยที่สุดเขียนโดยตรงไปยังไฟล์:

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

หรือเปิด / ปิดอย่างปลอดภัย:

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

หากคุณต้องการบันทึกไว้ในสตริงแทนที่จะเป็นไฟล์:

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


5

ในการเขียนไฟล์:

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

หากต้องการอ่านจากไฟล์:

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

myfile เป็นวัตถุไฟล์สำหรับไฟล์ที่คุณเก็บ dict ใน


คุณเป็นเครื่องที่ json มีที่ใช้ไฟล์เป็นข้อโต้แย้งและเขียนโดยตรงกับพวกเขา?

json.dump(myfile)และjson.load(myfile)
Niklas R

5

หากคุณเป็นอนุกรม แต่ไม่ต้องการข้อมูลในโปรแกรมอื่นฉันขอแนะนำshelveโมดูล คิดว่ามันเป็นพจนานุกรมถาวร

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
หากคุณต้องการเก็บ dict ทั้งหมดหรือโหลด dict ทั้งหมดjsonจะสะดวกกว่า shelveดีกว่าสำหรับการเข้าถึงครั้งละหนึ่งคีย์เท่านั้น
agf

3

หากคุณต้องการทางเลือกในการpickleหรือคุณสามารถใช้jsonklepto

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

ด้วยkleptoถ้าคุณใช้serialized=Trueพจนานุกรมจะถูกเขียนลงไปmemo.pklเป็นพจนานุกรมดองแทนด้วยข้อความที่ชัดเจน

คุณจะได้รับkleptoที่นี่: https://github.com/uqfoundation/klepto

dillอาจเป็นทางเลือกที่ดีกว่าสำหรับการดองแล้วpickleตัวมันเองเป็นdillอนุกรมได้เกือบทุกอย่างในหลาม kleptoยังสามารถใช้dillยังสามารถใช้

คุณจะได้รับdillที่นี่: https://github.com/uqfoundation/dill

mumbo-jumbo เพิ่มเติมในสองสามบรรทัดแรกเป็นเพราะkleptoสามารถกำหนดค่าให้เก็บพจนานุกรมลงในไฟล์ไปยังบริบทไดเร็กทอรีหรือไปยังฐานข้อมูล SQL API นั้นเหมือนกันสำหรับทุกสิ่งที่คุณเลือกเป็นไฟล์เก็บถาวรของแบ็กเอนด์ มันทำให้คุณมีพจนานุกรม " เก็บถาวร" ซึ่งคุณสามารถใช้loadและdumpโต้ตอบกับที่เก็บถาวร


3

นี่เป็นหัวข้อเก่า แต่เพื่อความสมบูรณ์เราควรรวม ConfigParser และ configparser ซึ่งเป็นส่วนหนึ่งของไลบรารีมาตรฐานใน Python 2 และ 3 ตามลำดับ โมดูลนี้อ่านและเขียนไปยังไฟล์ config / ini และ (อย่างน้อยใน Python 3) ทำงานในหลาย ๆ ทางเช่นพจนานุกรม มันมีประโยชน์เพิ่มเติมที่คุณสามารถจัดเก็บพจนานุกรมหลายรายการในส่วนที่แยกต่างหากของไฟล์ config / ini ของคุณและเรียกคืนได้ หวาน!

ตัวอย่าง 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)

ตัวอย่าง 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)

เอาต์พุตคอนโซล

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

เนื้อหาของ config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

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

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

1

หากบันทึกลงในไฟล์ json วิธีที่ดีที่สุดและง่ายที่สุดคือ:

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

ทำไมจึงเป็นเรื่องง่ายกว่าjson.dump( )ที่ระบุไว้ในคำตอบอื่น ๆ ?
baxx

0

กรณีการใช้งานของฉันคือการบันทึกวัตถุ json หลายรายการไว้ในคำตอบของไฟล์ช่วยฉันบ้าง แต่เพื่อใช้กรณีการใช้งานของฉันคำตอบนั้นไม่สมบูรณ์เนื่องจากมันจะเขียนทับข้อมูลเก่าทุกครั้งที่มีการบันทึกรายการใหม่

ในการบันทึกหลายรายการในไฟล์หนึ่งต้องตรวจสอบเนื้อหาเก่า (เช่นอ่านก่อนเขียน) ไฟล์ทั่วไปที่เก็บข้อมูล json จะมีlistหรือobjectเป็นรูท ดังนั้นฉันคิดว่าไฟล์ json ของฉันมีเสมอlist of objectsและทุกครั้งที่ฉันเพิ่มข้อมูลลงไปฉันเพียงแค่โหลดรายการก่อนต่อท้ายข้อมูลใหม่ของฉันในนั้นและทิ้งมันกลับไปที่อินสแตนซ์ไฟล์ที่เขียนได้อย่างเดียว ( 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"

ไฟล์ json ใหม่จะมีลักษณะดังนี้:

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

หมายเหตุ:มันเป็นสิ่งสำคัญที่จะมีไฟล์ชื่อfile.jsonกับ[]เป็นข้อมูลเบื้องต้นสำหรับวิธีการทำงาน

ป.ล. : ไม่เกี่ยวข้องกับคำถามเดิม แต่วิธีการนี้สามารถปรับปรุงได้อีกโดยการตรวจสอบก่อนว่ารายการของเรามีอยู่แล้ว (ขึ้นอยู่กับ 1 / หลายคีย์) แล้วต่อท้ายและบันทึกข้อมูล แจ้งให้เราทราบหากมีคนต้องการตรวจสอบนั้นฉันจะเพิ่มคำตอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.