首页 文章

将Dictionary的String表示形式转换为字典?

提问于
浏览
579

如何将 dictstr 表示(如下面的字符串)转换为 dict

s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"

我不想使用 eval . 我还能用什么?

这样做的主要原因是我写的一个同事类,将所有输入转换为字符串 . 我没有心情去修改他的课程来处理这个问题 .

11 回答

  • 6

    如果你不能使用Python 2.6,你可以使用简单的safeeval implmentntation,如http://code.activestate.com/recipes/364469/

    它背负着Python编译器,因此您不必自己完成所有的工作 .

  • 5

    以OP为例:

    s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
    

    我们可以使用Yaml来处理字符串中的这种非标准json:

    >>> import yaml
    >>> s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
    >>> s
    "{'muffin' : 'lolz', 'foo' : 'kitty'}"
    >>> yaml.load(s)
    {'muffin': 'lolz', 'foo': 'kitty'}
    
  • 915

    如果字符串总是可以信任的话,你可以使用 eval (或者按照建议使用 literal_eval ;无论字符串是什么,它都是安全的 . )否则你需要一个解析器 . 如果JSON解析器(例如simplejson)只存储符合JSON方案的内容,则它将起作用 .

  • 26

    使用 json . ast 库消耗大量内存并且速度较慢 . 我有一个需要读取156Mb文本文件的进程 . Ast 转换字典 json 延迟5分钟,内存减少60%!

  • 2

    你可以试试这个 .

    >>> import ast
        >>> data = "{'user': 'bob', 'age': 10, 'grades': ['A', 'F', 'C']}"
        >>> ast.literal_eval(data)
    
        O/P: {'age': 10, 'grades': ['A', 'F', 'C'], 'user': 'bob'}
    
        >>> user = ast.literal_eval(data)
    
        >>> user['age']
        O/P: 10
    
        >>> user['grades']
        O/P: ['A', 'F', 'C']
    
        >>> user['user']
        O/P: 'bob'
    
  • 144

    从Python 2.6开始,您可以使用内置的ast.literal_eval

    >>> import ast
    >>> ast.literal_eval("{'muffin' : 'lolz', 'foo' : 'kitty'}")
    {'muffin': 'lolz', 'foo': 'kitty'}
    

    这比使用 eval 更安全 . 正如自己的文档所说:

    >>> help(ast.literal_eval)
    Help on function literal_eval in module ast:
    
    literal_eval(node_or_string)
        Safely evaluate an expression node or a string containing a Python
        expression.  The string or node provided may only consist of the following
        Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
        and None.
    

    例如:

    >>> eval("shutil.rmtree('mongo')")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 1, in <module>
      File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 208, in rmtree
        onerror(os.listdir, path, sys.exc_info())
      File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 206, in rmtree
        names = os.listdir(path)
    OSError: [Errno 2] No such file or directory: 'mongo'
    >>> ast.literal_eval("shutil.rmtree('mongo')")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 68, in literal_eval
        return _convert(node_or_string)
      File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 67, in _convert
        raise ValueError('malformed string')
    ValueError: malformed string
    
  • 4

    http://docs.python.org/2/library/json.html

    JSON可以解决这个问题,虽然它的解码器需要围绕键和值的双引号 . 如果你不介意替换黑客......

    import json
    s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
    json_acceptable_string = s.replace("'", "\"")
    d = json.loads(json_acceptable_string)
    # d = {u'muffin': u'lolz', u'foo': u'kitty'}
    

    请注意,如果您将单引号作为键或值的一部分,则由于不正确的字符替换而失败 . 只有在您对eval解决方案有强烈厌恶的情况下,才建议使用此解决方案 .

    更多关于json单引号:jQuery single quote in JSON response

  • 21

    使用 json.loads

    >>> import json
    >>> h = '{"foo":"bar", "foo2":"bar2"}'
    >>> type(h)
    <type 'str'>
    >>> d = json.loads(h)
    >>> d
    {u'foo': u'bar', u'foo2': u'bar2'}
    >>> type(d)
    <type 'dict'>
    
  • 94
    string = "{'server1':'value','server2':'value'}"
    
    #Now removing { and }
    s = string.replace("{" ,"")
    finalstring = s.replace("}" , "")
    
    #Splitting the string based on , we get key value pairs
    list = finalstring.split(",")
    
    dictionary ={}
    for i in list:
        #Get Key Value pairs separately to store in dictionary
        keyvalue = i.split(":")
    
        #Replacing the single quotes in the leading.
        m= keyvalue[0].strip('\'')
        m = m.replace("\"", "")
        dictionary[m] = keyvalue[1].strip('"\'')
    
    print dictionary
    
  • 19

    没有使用任何库:

    dict_format_string = "{'1':'one', '2' : 'two'}"
    d = {}
    elems  = filter(str.isalnum,dict_format_string.split("'"))
    values = elems[1::2]
    keys   = elems[0::2]
    d.update(zip(keys,values))
    

    注意:由于它具有硬编码 split("'") 仅适用于数据为"single quoted"的字符串 .

  • 2

    总结一下:

    import ast, yaml, json, timeit
    
    descs=['short string','long string']
    strings=['{"809001":2,"848545":2,"565828":1}','{"2979":1,"30581":1,"7296":1,"127256":1,"18803":2,"41619":1,"41312":1,"16837":1,"7253":1,"70075":1,"3453":1,"4126":1,"23599":1,"11465":3,"19172":1,"4019":1,"4775":1,"64225":1,"3235":2,"15593":1,"7528":1,"176840":1,"40022":1,"152854":1,"9878":1,"16156":1,"6512":1,"4138":1,"11090":1,"12259":1,"4934":1,"65581":1,"9747":2,"18290":1,"107981":1,"459762":1,"23177":1,"23246":1,"3591":1,"3671":1,"5767":1,"3930":1,"89507":2,"19293":1,"92797":1,"32444":2,"70089":1,"46549":1,"30988":1,"4613":1,"14042":1,"26298":1,"222972":1,"2982":1,"3932":1,"11134":1,"3084":1,"6516":1,"486617":1,"14475":2,"2127":1,"51359":1,"2662":1,"4121":1,"53848":2,"552967":1,"204081":1,"5675":2,"32433":1,"92448":1}']
    funcs=[json.loads,eval,ast.literal_eval,yaml.load]
    
    for  desc,string in zip(descs,strings):
        print('***',desc,'***')
        print('')
        for  func in funcs:
            print(func.__module__+' '+func.__name__+':')
            %timeit func(string)        
        print('')
    

    结果:

    *** short string ***
    
    json loads:
    4.47 µs ± 33.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    builtins eval:
    24.1 µs ± 163 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    ast literal_eval:
    30.4 µs ± 299 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    yaml load:
    504 µs ± 1.29 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    *** long string ***
    
    json loads:
    29.6 µs ± 230 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    builtins eval:
    219 µs ± 3.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    ast literal_eval:
    331 µs ± 1.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    yaml load:
    9.02 ms ± 92.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    结论:更喜欢 json.loads

相关问题