Перетворіть діктову пітона в рядок і назад


275

Я пишу програму, яка зберігає дані в об’єкті словника, але ці дані потрібно зберегти в якийсь момент під час виконання програми та завантажувати назад у об’єкт словника при повторному запуску програми. Як би я перетворив об’єкт словника в рядок, який можна записати у файл та завантажити назад у об’єкт словника? Сподіваємось, це підтримка словників, що містять словники.

Відповіді:


274

Тут є хорошим рішенням модуль json . Переваги перед солінням мають переваги в тому, що він видає лише звичайний текст, а також є кросплатформою та крос-версією.

import json
json.dumps(dict)

2
Я також буду розглядати цей модуль. І json, і соління здаються досить простими у використанні, тому це зводиться до таких речей, як підтримка крос-платформ. Дякую
AJ00200

5
Підберезник, як правило, вважається досить застарілим у цій точці. Я завжди використовую json для таких речей. Бути (відносно) читаною людиною - це ВЕЛИКІ плюс багато часу.
Тайлер Евз

30
Вам слід додати простий приклад, щоб користувачі могли бачити, як це зробити.
Мігель Вацк

1
@TylerEaves Чи можете ви навести приклад того, як це потрібно зробити.
Бобан

1
: foreheadslap: не забувай, import jsonяк я зробив!
Джессі

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 або соління, але я знаю на факт, що eval в цьому випадку буде небезпечним.
AJ00200

5
@ AJ00200: і альтернативу ast.literal_eval, яку я згадав ?. З довідки Python: "Безпечно оцініть вузол виразів або рядок, що містить вираз Python. Наданий рядок або вузол може складатися лише з таких буквальних структур Python: рядки, числа, кортежі, списки, дикти, булеві та None. Це може бути використаний для безпечної оцінки рядків, що містять вирази Python з ненадійних джерел, без необхідності аналізувати самі значення ".
PabloG

Це здається корисним, але коли я раніше використовував SQLite для обробки цих даних, у ньому було понад 1500 записів, тому він досить великий і постійно зростає.
AJ00200

164

Я використовую json:

import json

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

# load to dict
my_dict = json.loads(input) 

14

Використовуйте pickleмодуль, щоб зберегти його на диску та завантажити потім.


2
@extraneon Власне, це відповідь на питання. Він десь перетворює його в рядок і записує у файл. Мені не потрібно робити фактичну конверсію чи запис файлів, оскільки це все інкапсульоване солінням.
AJ00200

11

Чому б не використати вбудовані в Python 3 Аст функції бібліотеки 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 () методу Python.

Припустимо, що словник:

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

І це буде зроблено так:

str(my_dict)

Буде надруковано:

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

Це легко, як вам подобається.


5

Якщо в Китаї

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": "Дон", "сюр

Перетворити рядок у словник

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прапор при відкритті файлу тут.
Пьотр Доброгост

1
Я міг би бути більш явним. Однак dumps()за замовчуванням використовується протокол 0, який є протоколом ascii. Ось чому 'rb'не потрібно ІМХО.
Джерард
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.