'How to convert a string to a dict from a list?

I have tried several ways to convert a dict-like str from a list to a dict, but cannot figure out how to interpret the error message correctly.

I have a list:

list = [(45, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': None, 'family': None}"), (12383, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': 'Fagales', 'family': None}"), (12384, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': 'Primulales', 'family': None}"), (12385, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': 'Magnoliales', 'family': None}"), (12386, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': 'Celastrales', 'family': None}")]

and want to convert the dict-like string into a dict, so I can access the values by key. I have tried:

test = (list[0][1]).replace("'", "\"")
dict(test)

but get the following error:

ValueError: dictionary update sequence element #0 has length 1; 2 is required

I also tried json.loads()

test2 = json.loads(test)

which returned:

JSONDecodeError: Expecting value: line 1 column 34 (char 33)

When I manually insert the string in the dict() function, the string successfully converts to a dict but not when using the list index. I would appreciate it if someone could explain why there is this difference and how I can convert the string directly into a dict.

Thanks for any help



Solution 1:[1]

You can use ast.literal_eval:

from ast import literal_eval

lst = [(45, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': None, 'family': None}"), (12383, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': 'Fagales', 'family': None}"), (12384, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': 'Primulales', 'family': None}"), (12385, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': 'Magnoliales', 'family': None}"), (12386, "{'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': 'Celastrales', 'family': None}")]

output = [(num, literal_eval(dct_rep)) for num, dct_rep in lst]

print(output) # [(45, {'kingdom': 'Plantae', 'phylum': None, 'class': None, 'order': None, 'family': None}), ...]
print(output[0][1]['kingdom']) # Plantae

The list comprehension converts each dict representation into a true dict. After that you can access the data in a more natural way.

Solution 2:[2]

I would look at eval

test_dict = eval(list[0][1])

Note: This is not recommended in production code as this can run any python code

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 j1-lee
Solution 2 AsynchronousGillz