Print complete key path for all the values of a python nested dictionary

As catavaran mentions, your problem is caused by adding the new path component to the path variable inside your for loop. You need to put the new path into the call so it gets passed to the next level of recursion and doesn't interfere with the path of subsequent items in the for loop at the current recursion level.

Here's an alternate solution that uses a recursive generator, rather than printing the results inside the dict_path function. (FWIW, I used print json.dumps(my_dict, indent=4) to reformat the dictionary).

my_dict = {
    "attr": {
        "types": {
            "category": "employee", 
            "tag": {
                "gender": "male", 
                "name": "Tom"
            }
        }
    }
}

def dict_path(my_dict, path=None):
    if path is None:
        path = []
    for k,v in my_dict.iteritems():
        newpath = path + [k]
        if isinstance(v, dict):
            for u in dict_path(v, newpath):
                yield u
        else:
            yield newpath, v

for path, v in dict_path(my_dict):
    print '_'.join(path), "=>", v

output

attr_types_category => employee
attr_types_tag_gender => male
attr_types_tag_name => Tom

You shouldn't alter the path variable in the dict_path() function:

def dict_path(path,my_dict):
    for k,v in my_dict.iteritems():
        if isinstance(v,dict):
            dict_path(path+"_"+k,v)
        else:
            print path+"_"+k,"=>",v
dict_path("",my_dict)