แปลง pict dython เป็นสตริงและย้อนกลับ


275

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

คำตอบ:


274

โมดูล jsonเป็นทางออกที่ดีที่นี่ มันมีข้อได้เปรียบเหนือ pickle ที่จะสร้างผลลัพธ์ข้อความล้วนและข้ามแพลตฟอร์มและข้ามรุ่น

import json
json.dumps(dict)

2
ฉันจะดูโมดูลนี้เช่นกัน ทั้ง json และ pickle นั้นดูใช้งานได้ง่ายดังนั้นมันจะลงมาที่สิ่งต่าง ๆ เช่นการรองรับข้ามแพลตฟอร์ม ขอบคุณ
AJ00200

5
ผักดองมีแนวโน้มที่จะถูกมองว่าเป็นที่ค่อนข้างคัดค้าน ณ จุดนี้ ฉันมักจะใช้ json สำหรับสิ่งต่าง ๆ เช่นนี้ การเป็นมนุษย์ (อ่านได้) เป็นสิ่งที่ยิ่งใหญ่และเป็นส่วนมาก
ไทเลอร์ชายคา

30
คุณควรเพิ่มตัวอย่างง่ายๆเพื่อให้ผู้ใช้เห็นวิธีการทำ
Miguel Vazq

1
@TylerEaves คุณสามารถให้ตัวอย่างว่ามันควรจะทำอย่างไร
Boban

1
: foreheadslap: อย่าลืมสิ่งที่import jsonฉันทำ!
Jesse Chisholm

207

หากพจนานุกรมของคุณไม่ใหญ่เกินไป str + eval ก็สามารถทำงานได้:

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

dict2 = eval(str1)

print dict1==dict2

คุณสามารถใช้ast.literal_evalแทน eval เพื่อความปลอดภัยเพิ่มเติมหากแหล่งที่ไม่น่าเชื่อถือ


13
ฉันไม่ได้เตรียมที่จะรับมือกับการหาประโยชน์ที่เป็นไปได้ซึ่งอาจนำไปสู่โค้ด ฉันไม่ทราบว่าปัญหา json หรือ pickle อาจมี แต่ฉันรู้ว่า eval จะเป็นอันตรายในกรณีนี้
AJ00200

5
@ AJ00200: และทางเลือก ast.literal_eval ฉันพูดถึง? จากวิธีใช้ Python: "ประเมินโหนดนิพจน์หรือสตริงที่มีนิพจน์ Python อย่างปลอดภัยสตริงหรือโหนดที่ระบุอาจประกอบด้วยโครงสร้างตัวอักษร Python ดังต่อไปนี้เท่านั้น: สตริงตัวเลข tuples รายการ dicts booleans และ None สิ่งนี้ สามารถใช้สำหรับการประเมินสตริงที่มีนิพจน์ Python อย่างปลอดภัยจากแหล่งข้อมูลที่ไม่น่าเชื่อถือโดยไม่จำเป็นต้องแยกวิเคราะห์ค่าของตนเอง "
PabloG

ดูเหมือนจะมีประโยชน์ แต่เมื่อก่อนหน้านี้ฉันใช้ SQLite เพื่อจัดการข้อมูลนี้และมีมากกว่า 1,500 รายการดังนั้นมันจึงค่อนข้างใหญ่และเติบโตตลอดเวลา
AJ00200


14

ใช้pickleโมดูลเพื่อบันทึกลงดิสก์และโหลดในภายหลัง


2
@extraneon จริงๆแล้วมันเป็นคำตอบสำหรับคำถาม มันจะแปลงเป็นสตริงที่ไหนสักแห่งและเขียนลงในไฟล์ ฉันไม่ต้องทำการแปลงจริงหรือเขียนไฟล์เพราะมันถูกห่อหุ้มด้วยดอง
AJ00200

11

ทำไมไม่ใช้งูหลาม 3 inbuilt ASTห้องสมุดของฟังก์ชั่นliteral_eval มันเป็นการดีกว่าที่จะใช้literal_evalแทนeval

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

จะให้ผลลัพธ์เป็นพจนานุกรมจริง

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

และถ้าคุณขอให้แปลงพจนานุกรมเป็นสตริงแล้ววิธีการใช้str ()วิธีการของหลาม

สมมติว่าพจนานุกรมคือ:

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

และจะทำเช่นนี้:

str(my_dict)

จะพิมพ์:

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

นี่เป็นวิธีที่ง่ายตามที่คุณต้องการ


5

หากอยู่ใน 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')

1
นี่จะเป็นคำตอบที่ดีกว่าถ้าคุณอธิบายว่าคุณให้รหัสตอบคำถามอย่างไร
pppery

4

แปลงพจนานุกรมเป็น JSON (สตริง)

import json 

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

result = json.dumps(mydict)

print(result[0:20])

คุณจะได้รับ:

{"name": "Don", "sur

แปลงสตริงเป็นพจนานุกรม

back_to_mydict = json.loads(result) 

3

ฉันคิดว่าคุณควรพิจารณาใช้ shelveโมดูลที่ให้วัตถุเหมือนพจนานุกรมที่มีไฟล์สำรอง มันใช้งานง่ายแทนพจนานุกรม "ของจริง" เพราะมันเกือบจะให้โปรแกรมของคุณมีบางอย่างที่สามารถใช้งานได้เหมือนพจนานุกรมโดยไม่จำเป็นต้องแปลงมันเป็นสตริงอย่างชัดเจนแล้วเขียนลงไฟล์ ในทางกลับกัน)

ความแตกต่างที่สำคัญคือจำเป็นต้องเริ่มต้นopen()ก่อนที่จะใช้งานครั้งแรกและจากนั้นclose()เมื่อคุณทำเสร็จ (และอาจเป็นไปsync()ได้ขึ้นอยู่กับwritebackตัวเลือกที่ใช้) วัตถุไฟล์ "ชั้นวาง" ใด ๆ ที่สร้างขึ้นสามารถมีพจนานุกรมปกติเป็นค่าทำให้พวกมันซ้อนกันอย่างมีเหตุผล

นี่เป็นตัวอย่างเล็กน้อย:

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

เอาท์พุท:

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

2

หากคุณสนใจความเร็วให้ใช้ujson (UltraJSON) ซึ่งมี API เดียวกับ 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]

1

ฉันใช้ yaml สำหรับสิ่งนั้นหากจำเป็นต้องอ่านได้ (ไม่ใช่ JSON หรือ XML เป็น IMHO) หรือหากไม่จำเป็นต้องอ่านฉันใช้ดอง

เขียน

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)

อ่านกลับ

from pickle import dumps, loads
rev = loads(open('/var/tmp/dump.txt').read())
print rev

คุณควรใช้bแฟล็กเมื่อเปิดไฟล์ที่นี่
Piotr Dobrogost

1
ฉันจะชัดเจนมากขึ้น อย่างไรก็ตามdumps()ค่าเริ่มต้นของโปรโตคอล 0 ซึ่งเป็นโปรโตคอล ASCII นั่นคือเหตุผลที่'rb'ไม่จำเป็นต้องมี IMHO
เจอราร์ด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.