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

Ube*_*per 719 python string dictionary

如何将a的str表示形式(dict如下面的字符串)转换为dict

s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
Run Code Online (Sandbox Code Playgroud)

我不喜欢用eval.我还能用什么?

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

Jac*_*son 1108

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

>>> import ast
>>> ast.literal_eval("{'muffin' : 'lolz', 'foo' : 'kitty'}")
{'muffin': 'lolz', 'foo': 'kitty'}
Run Code Online (Sandbox Code Playgroud)

这比使用更安全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
Run Code Online (Sandbox Code Playgroud)

  • @JuanB json.loads 不接受[单引号字符串](/sf/answers/3518005221/)。它也不接受 None,只接受 null。 (5认同)
  • 为什么不使用 json.dumps 和 json.loads insead,我发现这个解决方案比使用 eval 更重要 (3认同)
  • “dict(a=1)”样式字符串怎么样? (2认同)

ir0*_*539 202

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

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

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'}
Run Code Online (Sandbox Code Playgroud)

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

更多关于json单引号:jQuery单引号的JSON响应

  • `{"foo":"b'ar"}` (10认同)
  • 如果值为“None”(没有单引号,因此无法替换),则不起作用,例如“"{'d': None}"` (6认同)
  • `{'foo':( 1,2,3)}` (4认同)
  • 如果您有尾随逗号(不符合JSON),这也会失败,例如:"{'muffin':'lolz','foo':'kitty',}" (3认同)
  • 我正在寻找这个解决方案。`+1` 用于通知解码器需要在键和值周围使用双引号。 (2认同)
  • 另一个问题是`"{0: 'Hello'}"`。 (2认同)
  • 单引号字符串、元组文字和尾随逗号不是有效的 JSON。`json.loads` 仅适用于有效的 JSON 字符串。请参阅此处的规范:https://www.json.org/ 使用“json.loads”是最安全的解决方案,因此请尽可能使用。如果需要,我建议将您的输入转换为有效的 JSON。 (2认同)

tok*_*khi 138

使用json.loads:

>>> import json
>>> h = '{"foo":"bar", "foo2":"bar2"}'
>>> d = json.loads(h)
>>> d
{u'foo': u'bar', u'foo2': u'bar2'}
>>> type(d)
<type 'dict'>
Run Code Online (Sandbox Code Playgroud)

  • 我不认为它回答了OP的答案.我们如何使用json.laads将字符串s ="{'muffin':'lolz','foo':'kitty'}"转换成字典? (10认同)
  • 在我看来,这是最短最简单的方式......绝对是我个人喜欢的方式. (4认同)
  • @nostradamus 太多异常、浮点值、元组等等。 (3认同)
  • @technazi:json.loads(h.replace(“'”,'“')) (2认同)

lqh*_*gbl 31

以OP为例:

s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
Run Code Online (Sandbox Code Playgroud)

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

>>> import yaml
>>> s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
>>> s
"{'muffin' : 'lolz', 'foo' : 'kitty'}"
>>> yaml.load(s)
{'muffin': 'lolz', 'foo': 'kitty'}
Run Code Online (Sandbox Code Playgroud)

  • 这将导致 'yes' 和 'no' 字符串转换为 True / False (5认同)

Bli*_*ixt 22

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

  • 是的,这是一个很好的答案,但请注意,官方JSON不支持单引号字符串,如原始海报的示例中所示. (11认同)
  • 从2.6开始,simplejson作为json模块包含在Python标准库中. (8认同)

小智 19

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

  • 但有其局限性:尝试转换字符串"{'foo':'bar',}" (12认同)

小智 10

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
Run Code Online (Sandbox Code Playgroud)

  • 这种方法有很多错误。如果键的值包含 `{` 或 `}` 会怎样。如果它是嵌套的`dict`怎么办。如果值包含`,`怎么办? (3认同)

Ana*_*eev 8

总结一下:

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('')
Run Code Online (Sandbox Code Playgroud)

结果:

*** 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)
Run Code Online (Sandbox Code Playgroud)

结论:更喜欢json.loads

  • 除此之外,这对他的单引号字符串无效,这是他最初遇到的问题的一部分。性能从未被提及。 (5认同)
  • +1 表示基准(有助于做出明智的决定),-1 表示结论:正如多次提到的,“json”在很多情况下都会失败。应该由用户在功能与性能之间进行选择。 (4认同)

tsu*_*h97 7

Siva Kameswara Rao Munipalle 的优化代码

s = s.replace("{", "").replace("}", "").split(",")
            
dictionary = {}

for i in s:
    dictionary[i.split(":")[0].strip('\'').replace("\"", "")] = i.split(":")[1].strip('"\'')
            
print(dictionary)
Run Code Online (Sandbox Code Playgroud)


tam*_*aha 6

没有使用任何库(python2):

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))
Run Code Online (Sandbox Code Playgroud)

注意:由于它已硬编码,split("'")因此仅适用于数据为“单引号”的字符串。

注意2:在python3中,你需要换行filter()list()获取列表。