StringToDict and DictToString

Kamilche klachemin at home.com
Mon Jun 21 06:32:31 EDT 2004


I made this tonight, after discovering how bad it is to use eval() in
a server program. If someone knows of a better method, let me know!

import types

'''
Convert a string to a dict, or a dict to a string.
Not that comprehensive - it only handles strings, ints,
longs, floats, and None, but it's safer than using 'eval'
and trying to restrict the execution environment!
                                   --Kamilche

Sample output:
--------------
orig dict: {'int': 1, 'none': None, 'float': 1.0,
            'string': 'string', 'long': 12345678901234567890L}
to string: ' int 1 none None float 1.0 string string long
12345678901234567890'
to dict:   {'int': 1, 'none': None, 'float': 1.0,
            'string': 'string', 'long': 12345678901234567890L}

'''

def StringToDict(s):
    '''
    Convert a string to a dict.
    The first char of the string is the delimiter for the items.
    Try to parse it, and on failure, return an empty dict.
    '''
    if type(s) != types.StringType:
        raise Exception("Arg to StringToDict must be a string!")
    try:
        if len(s) < 4:
            return {}
        delim = s[0]
        tokens = s.split(delim)
        i = 1
        max = len(tokens) - 1
        d = {}
        while i < max:
            key = tokens[i]
            value = StringToValue(tokens[i + 1])
            d[key] = value
            i += 2
        return d
    except:
        return {}

def DictToString(d, delim = '\t'):
    '''
    Convert a dict to a string. If the str() of any key or value
    in the dict contains the delimiter, raise an error. Otherwise,
    insert the delimiter into the first character of the string.
    '''
    tokens = []
    if type(d) != types.DictType:
        raise Exception("Argument must be a dict!")
    if len(d) == 0:
        return ''
    if len(delim) != 1:
        raise Exception("Delimiter must be a single character!")
    tokens.append('')
    for key, value in d.items():
        key = str(key)
        value = str(value)
        if delim in key or delim in value:
            raise Exception("Pick a different delimiter for
DictToString, your data uses %s!" % delim)
        tokens.append(key)
        tokens.append(value)
    return delim.join(tokens)
        
def StringToValue(s):
    " Convert a string to the 'best guess' type"
    if type(s) != type(""):
        return s
    if len(s) == 0:
        return s 
    if s in ('None', 'none'):
        return None
    if (s[0] in "+-0123456789.") and ("." in s):
        try:
            v = float(s)
            return v
        except:
            pass
    if s[0] in "+-0123456789":
        try:
            v = int(s)
            return v
        except:
            try:
                v = long(s)
                return v
            except:
                pass
    return s

def test(**d):
    print "orig dict:", d
    s = DictToString(d, ' ')
    print "to string: '" + s + "'"
    print "to dict:  ", StringToDict(s)
    print

def main():
    test()
    test(string = 'string', int = 1, float = 1.0, long =
12345678901234567890, none = None)
        
if __name__ == "__main__":
    main()



More information about the Python-list mailing list