I have a script that changes a dict to a string and saves it to a file. I'd like to then load that file and use it as a dict, but it's a string. Is there something like int("7") that can change a string formatted as a dict ({a: 1, b: 2}) into a dict? I've tried dict(), but this doesn't seem to be what it does. I've heard of some process involving JSON and eval(), but I don't really see what this does. The program loads the same data it saves, and if someone edits it and it doesn't work, it's no problem of mine (I don't need any advanced method of confirming the dict data or anything).
4 Answers
Try this, it's the safest way:
import ast ast.literal_eval("{'x':1, 'y':2}") => {'y': 2, 'x': 1} All the solutions based in eval() are dangerous, malicious code could be injected inside the string and get executed.
According to the documentation the expression gets evaluated safely. Also, according to the source code, literal_eval parses the string to a python AST (source tree), and returns only if it is a literal. The code is never executed, only parsed, so there is no reason for it to be a security risk.
7 Comments
ast module, thanks for this one!ast.literal_eval only works on literals. sourceliteral_eval parses the string to a python AST (source tree), and returns only if it is a literal. The code is never executed, only parsed, so there is no reason to be a security riskast, but I wouldn't have thought of using it here. +1This format is not JSON, but YAML, which you can parse with PyYAML:
>>> import yaml >>> s = '{a: 1, b: 2}' >>> d = yaml.load(s) >>> d {'a': 1, 'b': 2} >>> type(d) <type 'dict'> 2 Comments
You can use eval if you trust the input string.
>>> a=eval('{"a":1,"b":2}') >>> a {'a': 1, 'b': 2} 10 Comments
eval is generally a bad idea.eval? People act like string-to-dict is like feeding data from online directly into a root command line.eval would be okay if you're completely confident that the output is safe. But, if you don't, it could be as bad as feeding data from online directly into the command line - for example, if somebody swapped the expected input with an os.system call.eval in your program would happily run it.Serialization
What you are talking about doing is object serialization, and there are better ways of doing it than rolling your own serialization method (though you seem to have come up with YAML). Both of these are still less secure than the ast.literal_eval() approach (pickle particularly), but they definitely should be noted here.
JSON
Here is an example of doing what you want using JSON, a popular cross-language format:
import json myDict = {'a':1, 'b':2} # write to the file 'data' with open('data','w') as f: json.dump(myDict, f) # now we can load it back with open('data','r') as f: myDictLoaded = json.load(f) print myDictLoaded Output:
{u'a': 1, u'b': 2} pickle
Here is a second example doing the same thing using pickle. pickle is more powerful in that it can serialize all* python objects, even ones you write.
import cPickle as pickle myDict = {'a':1, 'b':2} # write to the file 'data' with open('data','w') as f: pickle.dump(myDict, f) # now we can load it back with open('data','r') as f: myDictLoaded = pickle.load(f) print myDictLoaded Output:
{'a': 1, 'b': 2}
dictwhy don't you just use pickle?pickleto ease the transition.pickleis one way to do that.