How to check if a string contains a dictionary

I want to recursively parse all values ​​in a dict that are strings with ast.literal_eval(value), but not do this eval if the string does not contain a dict. I want this because I have a string in a dict, which in itself is a dict, and I would like the value to be dict. Best example

my_dict = {'a': 42, 'b': "my_string", 'c': "{'d': 33, 'e': 'another string'}"}

Now I do not want to do ast.literal_eval(my_dict['c'])I want to use a general solution in which I can makeconvert_to_dict(my_dict)

I wanted to write my own method, but I don’t know how to check if the string contains a dict and then ast.literal_eval will fail, so the question is.

+4
source share
5 answers

, . :

def recursive_dict_eval(myDict):
    for key,value in myDict.items():
        try:
            if(isinstance(value, dict)):
                recursive_dict_eval(value)
            evaled_value=ast.literal_eval(value)
            assert isinstance(evaled_value,dict)
            myDict[key]=recursive_dict_eval(evaled_value)

        except (SyntaxError, ValueError, AssertionError):
            #SyntaxError, ValueError are for the literal_eval exceptions
            pass
    return myDict
0

, . , , , dict, , . dict, , :

import ast
my_dict = {'a': 42, 'b': "my_string", 'c': "{'d': 33, 'e': \"{'f' : 64}\"}"}

def recursive_dict_eval(old_dict):
    new_dict = old_dict.copy()
    for key,value in old_dict.items():
        try:
            evaled_value=ast.literal_eval(value)
            assert isinstance(evaled_value,dict)
            new_dict[key]=recursive_dict_eval(evaled_value)

        except (SyntaxError, ValueError, AssertionError):
            #SyntaxError, ValueError are for the literal_eval exceptions
            pass
    return new_dict

print(my_dict)
print(recursive_dict_eval(my_dict))

:

{'a': 42, 'b': 'my_string', 'c': '{\'d\': 33, \'e\': "{\'f\' : 64}"}'}
{'a': 42, 'b': 'my_string', 'c': {'e': {'f': 64}, 'd': 33}}
+2

, , , . , , . , . , .

my_dict = {'a': 42, 'b': "my_string", 'c': "{'d': 33, 'e': 'another string'}"}

def convert_to_dict(d):
    for key, val in d.items():
        try:
            check = ast.literal_eval(val)
        except:
            continue 
        if isinstance(check, dict):
            d[key] = check 
    return d

convert_to_dict(my_dict)
+1

, dict literal_eval :

from ast import literal_eval

def reassign(d):
    for k, v in d.items():
        try:
            evald = literal_eval(v)
            if isinstance(evald, dict):
                d[k] = evald
        except ValueError:
            pass

dict:

In [2]: my_dict = {'a': 42, 'b': "my_string", 'c': "{'d': 33, 'e': 'another stri
   ...: ng'}"}

In [3]: reassign(my_dict)

In [4]: my_dict
Out[4]: {'a': 42, 'b': 'my_string', 'c': {'d': 33, 'e': 'another string'}}

In [5]: my_dict = {'a': '42', 'b': "my_string", '5': "{'d': 33, 'e': 'another st
...: ring', 'other_dict':{'foo':'bar'}}"}
In [6]: reassign(my_dict)  
In [7]: my_dict
Out[7]: 
{'5': {'d': 33, 'e': 'another string', 'other_dict': {'foo': 'bar'}},
 'a': '42',
 'b': 'my_string'}

, datetime .., literal_eval , , dict , .

, dict.

def reassign(d):
    for k, v in d.items():
        try:
            evald = literal_eval(v)
            if isinstance(evald, dict):
                d[k] = evald
                reassign(evald)
        except ValueError:
            pass

dict:

In [10]: my_dict = {'a': 42, 'b': "my_string", 'c': "{'d': 33, 'e': \"{'f' : 64}
    ...: \"}"}

In [11]: reassign(my_dict)

In [12]: my_dict
Out[12]: {'a': 42, 'b': 'my_string', 'c': {'d': 33, 'e': {'f': 64}}}

dict:

from ast import literal_eval
from copy import deepcopy

def reassign(d):
    for k, v in d.items():
        try:
            evald = literal_eval(v)
            if isinstance(evald, dict):
                yield k, dict(reassign(evald))
        except ValueError:
            yield k, deepcopy(v)

dict:

In [17]: my_dict = {'a': [1, 2, [3]], 'b': "my_string", 'c': "{'d': 33, 'e': \"{
    ...: 'f' : 64}\"}"}

In [18]: new =  dict(reassign(my_dict))

In [19]: my_dict["a"][-1].append(4)

In [20]: new
Out[20]: {'a': [1, 2, [3]], 'b': 'my_string', 'c': {'d': 33, 'e': {'f': 64}}}

In [21]: my_dict
Out[21]: 
{'a': [1, 2, [3, 4]],
 'b': 'my_string',
 'c': '{\'d\': 33, \'e\': "{\'f\' : 64}"}'}

, dict, , .

+1

str dict, json.loads object_hook :

import json

def convert_subdicts(d):
    for k, v in d.items():
        try:
            # Try to decode a dict
            newv = json.loads(v, object_hook=convert_subdicts)
        except Exception:
            continue
        else:
            if isinstance(newv, dict):
                d[k] = newv  # Replace with decoded dict
    return d

origdict = {'a': 42, 'b': "my_string", 'c': "{'d': 33, 'e': 'another string'}"}
newdict = convert_subdicts(origdict.copy())  # Omit .copy() if mutating origdict okay

This should recursively handle the case where the contained ones dictmay contain values strthat define sub-entities. If you do not need to handle this case, you can omit use object_hookor replace json.loadscompletely with ast.literal_eval.

0
source

Source: https://habr.com/ru/post/1658102/


All Articles