Menyimpan kamus Python

198

Saya terbiasa membawa data masuk dan keluar dari Python menggunakan file .csv, tetapi ada tantangan yang jelas untuk ini. Adakah saran tentang cara-cara sederhana untuk menyimpan kamus (atau kumpulan kamus) dalam file json atau pck? Sebagai contoh:

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

Saya ingin tahu keduanya cara menyimpan ini, dan kemudian cara memuatnya kembali.

mike
sumber
8
Sudahkah Anda membaca dokumentasi untuk modul standar json atau acar ?
Greg Hewgill

Jawaban:

443

Acar simpan:

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)

Lihat dokumentasi modul acar untuk informasi tambahan mengenai protocolargumen tersebut.

Beban acar :

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

JSON simpan:

import json

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

Berikan argumen tambahan seperti sort_keysatau indentuntuk mendapatkan hasil yang cantik. Argumen sort_keys akan mengurutkan kunci secara abjad dan indentasi akan membuat indentasi struktur data Anda dengan indent=Nspasi.

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

Beban JSON :

with open('data.json', 'r') as fp:
    data = json.load(fp)
Marty
sumber
4
JSON membuat kamus secara asli (meskipun mereka jelas tidak berperilaku persis seperti kamus python sementara di memori, untuk tujuan kegigihan, mereka identik). Bahkan, unit dasar dalam json adalah "Object", yang didefinisikan sebagai {<string>: <value>}. Terlihat familier? Modul json di perpustakaan standar mendukung setiap jenis asli Python dan dapat dengan mudah diperluas dengan pengetahuan minimal json untuk mendukung kelas yang ditentukan pengguna. Halaman utama JSON sepenuhnya mendefinisikan bahasa hanya dalam 3 halaman cetakan, sehingga mudah diserap / dicerna dengan cepat.
Jonathanb
1
Perlu juga diketahui tentang argumen ketiga pickle.dumpjuga. Jika file tidak harus dapat dibaca oleh manusia maka itu dapat mempercepat banyak hal.
Steve Jessop
11
Jika Anda menambahkan sort_keys dan membuat indentasi argumen ke panggilan dump Anda mendapatkan hasil yang jauh lebih cantik. misalnya: json.dump(data, fp, sort_keys=True, indent=4). Info lebih lanjut dapat ditemukan di sini
juliusmh
1
Anda mungkin harus menggunakanpickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Martin Thoma
1
Untuk python 3, gunakanimport pickle
hazard89
35

Contoh minimal, menulis langsung ke file:

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

atau membuka / menutup dengan aman:

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

Jika Anda ingin menyimpannya dalam string, bukan file:

import json
json_str = json.dumps(data)
data = json.loads(json_str)
agf
sumber
5

Untuk menulis ke file:

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

Untuk membaca dari file:

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

myfile adalah objek file untuk file tempat Anda menyimpan dict.

Rafe Kettler
sumber
Anda yakin bahwa json memiliki file yang diambil sebagai argumen dan menulis langsung kepada mereka?
json.dump(myfile)danjson.load(myfile)
Niklas R
5

Jika Anda menginginkan serialisasi tetapi tidak membutuhkan data di program lain, saya sangat merekomendasikan shelvemodul ini. Anggap saja sebagai kamus persisten.

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()
gddc
sumber
2
Jika Anda ingin menyimpan seluruh dict, atau memuat seluruh dict, jsonlebih mudah. shelvehanya lebih baik untuk mengakses satu kunci sekaligus.
AGF
3

Jika Anda ingin alternatif pickleatau json, Anda dapat menggunakanklepto .

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

Dengan klepto, jika Anda pernah menggunakannyaserialized=True , kamus akan ditulis memo.pklsebagai kamus acar dan bukan dengan teks yang jelas.

Anda bisa sampai di kleptosini: https://github.com/uqfoundation/klepto

dillmungkin merupakan pilihan yang lebih baik untuk pengawetan dengan picklesendirinya, karena dilldapat membuat serialisasi hampir semua hal dengan python. kleptojuga bisa digunakan dill.

Anda bisa sampai di dillsini: https://github.com/uqfoundation/dill

Mumbo-jumbo tambahan pada beberapa baris pertama adalah karena kleptodapat dikonfigurasi untuk menyimpan kamus ke file, ke konteks direktori, atau ke database SQL. API adalah sama untuk apa pun yang Anda pilih sebagai arsip backend. Ini memberi Anda kamus "dapat diarsipkan" dengan mana Anda dapat menggunakan loaddan dumpuntuk berinteraksi dengan arsip.

Mike McKerns
sumber
3

Ini adalah topik lama, tetapi untuk kelengkapan, kita harus menyertakan ConfigParser dan configparser yang masing-masing merupakan bagian dari pustaka standar di Python 2 dan 3. Modul ini membaca dan menulis ke file config / ini dan (setidaknya dalam Python 3) berperilaku seperti kamus. Ini memiliki manfaat tambahan bahwa Anda dapat menyimpan beberapa kamus ke dalam bagian terpisah dari file konfigurasi Anda dan mengingatnya. Manis!

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

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

output konsol

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

isi dari config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

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

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

Jika menyimpan ke file json, cara terbaik dan termudah untuk melakukan ini adalah:

import json
with open("file.json", "wb") as f:
    f.write(json.dumps(dict).encode("utf-8"))
Adam Liu
sumber
mengapa ini lebih mudah daripada yang json.dump( )diuraikan dalam jawaban lain?
baxx
0

kasus penggunaan saya adalah untuk menyimpan beberapa objek json ke file dan jawaban marty agak membantu saya. Tetapi untuk melayani kasus penggunaan saya, jawabannya tidak lengkap karena akan menimpa data lama setiap kali entri baru disimpan.

Untuk menyimpan banyak entri dalam file, seseorang harus memeriksa konten lama (yaitu, baca sebelum menulis). File tipikal yang menyimpan data json akan memiliki root listatau objectsebagai. Jadi saya menganggap bahwa file json saya selalu memiliki list of objectsdan setiap kali saya menambahkan data ke dalamnya, saya cukup memuat daftar terlebih dahulu, menambahkan data baru saya di dalamnya dan membuangnya kembali ke contoh file yang hanya dapat ditulisi ( 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"

file json baru akan terlihat seperti ini:

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

CATATAN: Sangat penting untuk memiliki file bernama file.jsondengan []sebagai data awal untuk pendekatan ini untuk bekerja

PS: tidak terkait dengan pertanyaan awal, tetapi pendekatan ini juga dapat lebih ditingkatkan dengan terlebih dahulu memeriksa apakah entri kita sudah ada (berdasarkan 1 / beberapa kunci) dan baru kemudian menambahkan dan menyimpan data. Beri tahu saya jika seseorang membutuhkan pemeriksaan itu, saya akan menambahkan jawabannya

ansh sachdeva
sumber