Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to turn a string with unquoted keys into a dict in Python

Tags:

python

I have a string

"{a:'b', c:'d',e:''}"

Please not that the keys to the dictionary entries are unquoted, so a simple eval("{a:'b', c:'d',e:''}") as suggested in a previous question does not work.

What would be the most convenient way to convert this string to a dictionary?

{'a':'b', 'c':'d', 'e':''}
like image 493
Harrison Avatar asked Jun 21 '16 05:06

Harrison


2 Answers

If this is from a trusted source (do not use this for general user input, as eval is not secure; but then again, if you're getting input from a potentially malicious user you should use JSON format and the json module instead), you can use eval with a trick.

source = """{e: '', a: 'b', c: 'd'}"""

class identdict(dict):
    def __missing__(self, key):
        return key

d = eval(source, identdict())
print(d)

prints

{'a': 'b', 'c': 'd', 'e': ''}

How this works is that we create a new dictionary subclass identdict that defines the magic method __missing__. This method is called for lookups on keys that are missing from the dictionary. In this case, we just return the key, so the dictionary maps keys to themselves. Then the source is evaluated using an identdict instance as the globals argument. eval will look up the values of variables from the globals mapping; as it is an identdict, the value of each variable accessed is conveniently now the name of the variable.

Works for even more complex strings as values, and anything that is proper Python literal syntax.

like image 106

Depending on the complexity of what you're parsing, this could work:

s = "{a:'b', c:'d',e:''}"
d = dict([
    (x.split(':')[0].strip(), x.split(':')[1].strip("' "))
    for x in s.strip("{}").split(',')
])
like image 27
Will Avatar answered Oct 04 '22 12:10

Will