Ubah dict python menjadi string dan kembali

275

Saya menulis sebuah program yang menyimpan data dalam objek kamus, tetapi data ini perlu disimpan di beberapa titik selama pelaksanaan program dan dimuat kembali ke objek kamus ketika program dijalankan kembali. Bagaimana saya mengubah objek kamus menjadi string yang dapat ditulis ke file dan dimuat kembali ke objek kamus? Mudah-mudahan ini akan mendukung kamus yang berisi kamus.

AJ00200
sumber

Jawaban:

274

Modul json adalah solusi yang bagus di sini. Ini memiliki kelebihan dibandingkan acar yang hanya menghasilkan output teks biasa, dan bersifat lintas platform dan lintas versi.

import json
json.dumps(dict)
Tyler Eaves
sumber
2
Saya akan melihat modul ini juga. Baik json dan acar tampaknya cukup mudah digunakan, sehingga akan mengarah ke hal-hal seperti dukungan lintas platform. Terima kasih
AJ00200
5
Acar cenderung dianggap agak usang pada saat ini. Saya selalu menggunakan json untuk hal-hal seperti ini. Menjadi (relatif) dapat dibaca manusia adalah BESAR ditambah banyak waktu.
Tyler Eaves
30
Anda harus menambahkan contoh sederhana untuk memungkinkan pengguna melihat bagaimana melakukan itu.
Miguel Vazq
1
@TylerEaves Bisakah Anda memberikan contoh bagaimana hal itu harus dilakukan.
Boban
1
: foreheadslap: jangan lupa import jsonseperti yang saya lakukan!
Jesse Chisholm
207

Jika kamus Anda tidak terlalu besar, mungkin str + eval dapat melakukan tugasnya:

dict1 = {'one':1, 'two':2, 'three': {'three.1': 3.1, 'three.2': 3.2 }}
str1 = str(dict1)

dict2 = eval(str1)

print dict1==dict2

Anda dapat menggunakan ast.literal_eval alih-alih eval untuk keamanan tambahan jika sumbernya tidak dipercaya.

PabloG
sumber
13
Saya tidak benar-benar siap untuk berurusan dengan kemungkinan eksploitasi yang dapat dimasukkan ke dalam kode ini. Saya tidak tahu masalah apa yang mungkin dimiliki json atau acar, tetapi saya tahu pasti bahwa eval akan berbahaya dalam kasus ini.
AJ00200
5
@ AJ00200: dan alternatif ast.literal_eval yang saya sebutkan ?. Dari bantuan Python: "Mengevaluasi simpul ekspresi atau string yang berisi ekspresi Python dengan aman. String atau simpul yang disediakan hanya dapat terdiri dari struktur literal Python berikut: string, angka, tupel, daftar, dikt, boolean, dan Tidak Ada. Ini dapat digunakan untuk mengevaluasi string yang berisi ekspresi Python dari sumber yang tidak dipercaya dengan aman tanpa harus menguraikan nilai sendiri. "
PabloG
Tampaknya memang bermanfaat, tetapi ketika saya sebelumnya menggunakan SQLite untuk menangani data ini dan memiliki lebih dari 1500 entri, sehingga cukup besar dan terus bertambah.
AJ00200
164

Saya menggunakan json:

import json

# convert to string
input = json.dumps({'id': id })

# load to dict
my_dict = json.loads(input) 
Eyal Ch
sumber
14

Gunakan picklemodul untuk menyimpannya ke disk dan memuat nanti.

ismail
sumber
2
@extraneon Sebenarnya, ini adalah jawaban untuk pertanyaan itu. Itu mengubahnya menjadi string di suatu tempat dan menulisnya ke file. Saya tidak perlu melakukan konversi atau penulisan file yang sebenarnya karena semuanya dienkapsulasi oleh acar.
AJ00200
11

Mengapa tidak menggunakan fungsi ast library inbuilt Python 3 literal_eval . Lebih baik menggunakan literal_eval daripada eval

import ast
str_of_dict = "{'key1': 'key1value', 'key2': 'key2value'}"
ast.literal_eval(str_of_dict)

akan memberikan output sebagai Kamus aktual

{'key1': 'key1value', 'key2': 'key2value'}

Dan Jika Anda meminta untuk mengonversi Kamus ke String , Bagaimana dengan menggunakan str () metode dari Python.

Misalkan kamus adalah:

my_dict = {'key1': 'key1value', 'key2': 'key2value'}

Dan ini akan dilakukan seperti ini:

str(my_dict)

Akan Cetak:

"{'key1': 'key1value', 'key2': 'key2value'}"

Ini semudah yang kamu mau.

FightWithCode
sumber
5

Jika di Chinses

import codecs
fout = codecs.open("xxx.json", "w", "utf-8")
dict_to_json = json.dumps({'text':"中文"},ensure_ascii=False,indent=2)
fout.write(dict_to_json + '\n')
beta
sumber
1
Ini akan menjadi jawaban yang lebih baik jika Anda menjelaskan bagaimana kode yang Anda berikan menjawab pertanyaan itu.
pppery
4

Konversi kamus menjadi JSON (string)

import json 

mydict = { "name" : "Don", 
          "surname" : "Mandol", 
          "age" : 43} 

result = json.dumps(mydict)

print(result[0:20])

akan membuat Anda:

{"name": "Don", "sur

Ubah string menjadi kamus

back_to_mydict = json.loads(result) 
Harvey
sumber
3

Saya pikir Anda harus mempertimbangkan untuk menggunakan shelve modul yang menyediakan objek seperti kamus yang didukung file yang persisten. Mudah digunakan sebagai pengganti kamus "nyata" karena hampir secara transparan menyediakan program Anda dengan sesuatu yang dapat digunakan seperti kamus, tanpa perlu secara eksplisit mengubahnya menjadi string dan kemudian menulis ke file (atau sebaliknya). sebaliknya).

Perbedaan utama adalah perlu awalnya open()sebelum digunakan pertama dan kemudian close()ketika Anda selesai (dan mungkin sync()itu, tergantung padawriteback opsi yang digunakan). Setiap objek file "rak" yang dibuat dapat berisi kamus reguler sebagai nilai, yang memungkinkan mereka untuk secara logis bersarang.

Berikut ini contoh sepele:

import shelve

shelf = shelve.open('mydata')  # open for reading and writing, creating if nec
shelf.update({'one':1, 'two':2, 'three': {'three.1': 3.1, 'three.2': 3.2 }})
shelf.close()

shelf = shelve.open('mydata')
print shelf
shelf.close()

Keluaran:

{'three': {'three.1': 3.1, 'three.2': 3.2}, 'two': 2, 'one': 1}
martineau
sumber
2

Jika Anda peduli tentang kecepatan gunakan ujson (UltraJSON), yang memiliki API yang sama dengan json:

import ujson
ujson.dumps([{"key": "value"}, 81, True])
# '[{"key":"value"},81,true]'
ujson.loads("""[{"key": "value"}, 81, true]""")
# [{u'key': u'value'}, 81, True]
Tomasz Bartkowiak
sumber
1

Saya menggunakan yaml untuk itu jika perlu dibaca (baik JSON atau XML adalah IMHO), atau jika membaca tidak perlu, saya menggunakan acar.

Menulis

from pickle import dumps, loads
x = dict(a=1, b=2)
y = dict(c = x, z=3)
res = dumps(y)
open('/var/tmp/dump.txt', 'w').write(res)

Baca kembali

from pickle import dumps, loads
rev = loads(open('/var/tmp/dump.txt').read())
print rev
Gerard
sumber
Anda harus benar-benar menggunakan btanda saat membuka file di sini.
Piotr Dobrogost
1
Saya bisa lebih eksplisit. Namun dumps()default ke protokol 0, yang merupakan protokol ascii. Itu sebabnya 'rb'tidak perlu IMHO.
Gerard