Converti un dict python in una stringa e viceversa


275

Sto scrivendo un programma che memorizza i dati in un oggetto dizionario, ma questi dati devono essere salvati ad un certo punto durante l'esecuzione del programma e caricati nuovamente nell'oggetto dizionario quando il programma viene eseguito nuovamente. Come posso convertire un oggetto dizionario in una stringa che può essere scritta in un file e ricaricata in un oggetto dizionario? Si spera che questo supporti dizionari contenenti dizionari.

Risposte:


274

Il modulo json è una buona soluzione qui. Ha i vantaggi rispetto a pickle che produce solo output in testo normale, ed è multipiattaforma e cross-version.

import json
json.dumps(dict)

2
Daremo un'occhiata anche a questo modulo. Sia json che pickle sembrano abbastanza facili da usare, quindi dipenderà da cose come il supporto multipiattaforma. Grazie
AJ00200 il

5
Pickle tende ad essere visto come piuttosto deprecato a questo punto. Uso sempre JSON per cose come questa. Essere (relativamente) leggibili dall'uomo è un GRANDE più del tempo.
Tyler Eaves,

30
Dovresti aggiungere un semplice esempio per consentire agli utenti di vedere come farlo.
Miguel Vazq,

1
@TylerEaves Puoi fornire un esempio di come dovrebbe essere fatto.
Boban,

1
: fronte: non dimenticare import jsoncome ho fatto io!
Jesse Chisholm,

207

Se il tuo dizionario non è troppo grande forse str + eval può fare il lavoro:

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

dict2 = eval(str1)

print dict1==dict2

È possibile utilizzare ast.literal_eval anziché eval per ulteriore sicurezza se l'origine non è attendibile.


13
Non sono davvero pronto a gestire i possibili exploit che questo potrebbe introdurre nel codice. Non so quali potrebbero essere i problemi di json o pickle, ma so per certo che in questo caso eval sarebbe pericoloso.
AJ00200,

5
@ AJ00200: e l'alternativa ast.literal_eval di cui ho parlato ?. Dalla guida di Python: "Valuta in modo sicuro un nodo di espressione o una stringa contenente un'espressione di Python. La stringa o il nodo forniti possono essere costituiti solo dalle seguenti strutture letterali di Python: stringhe, numeri, tuple, elenchi, dadi, valori booleani e Nessuno. può essere utilizzato per valutare in modo sicuro stringhe contenenti espressioni Python da fonti non attendibili senza la necessità di analizzare i valori da soli. "
PabloG,

Sembra utile, ma quando in precedenza utilizzavo SQLite per gestire questi dati e aveva oltre 1500 voci, quindi è abbastanza grande e in costante crescita.
AJ00200,

164

Io uso json:

import json

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

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

14

Utilizzare il picklemodulo per salvarlo su disco e caricarlo in seguito.


2
@extraneon In realtà, è una risposta alla domanda. Lo converte in una stringa da qualche parte e lo scrive in un file. Non devo fare la conversione o la scrittura dei file in quanto è tutto incapsulato da pickle.
AJ00200,

11

Perché non usare integrato di Python 3 ast la funzione della biblioteca literal_eval . È meglio usare literal_eval invece di eval

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

fornirà l'output come dizionario effettivo

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

E se stai chiedendo di convertire un dizionario in una stringa , allora, che ne dici di usare il metodo str () di Python.

Supponiamo che il dizionario sia:

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

E questo sarà fatto in questo modo:

str(my_dict)

Stampa:

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

Questo è facile come preferisci.


5

Se in cinese

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
Questa sarebbe una risposta migliore se spiegassi come il codice che hai fornito risponde alla domanda.
pepery

4

Converti dizionario in JSON (stringa)

import json 

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

result = json.dumps(mydict)

print(result[0:20])

ti porterà:

{"name": "Don", "sur

Converti la stringa in dizionario

back_to_mydict = json.loads(result) 

3

Penso che dovresti prendere in considerazione l'uso del shelvemodulo che fornisce persistenti oggetti simili a dizionari supportati da file. È facile da usare al posto di un dizionario "reale" perché fornisce in modo quasi trasparente al tuo programma qualcosa che può essere usato proprio come un dizionario, senza la necessità di convertirlo esplicitamente in una stringa e quindi scrivere in un file (o viceversa versa).

La differenza principale è che inizialmente open()è necessario prima del primo utilizzo e poi close()quando hai finito (e possibilmente sync()ing, a seconda writebackdell'opzione utilizzata). Qualsiasi oggetto file "shelf" creato può contenere dizionari regolari come valori, consentendo di annidarli logicamente.

Ecco un esempio banale:

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

Produzione:

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

2

Se ti interessa la velocità usa ujson (UltraJSON), che ha la stessa API di 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

Uso yaml per questo se deve essere leggibile (né JSON né XML sono quell'IMHO), o se la lettura non è necessaria uso pickle.

Scrivi

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)

Rileggi

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

Dovresti davvero usare bflag quando apri il file qui.
Piotr Dobrogost,

1
Avrei potuto essere più esplicito. Tuttavia, il dumps()valore predefinito è il protocollo 0, che è un protocollo ASCII. Ecco perché 'rb'non è necessario IMHO.
Gerard,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.