Python将字符串转换为字典。

15

我有一个字符串:

'{tomatoes : 5 , livestock :{cow : 5 , sheep :2 }}' 

并且希望将其转换为

{
  "tomatoes" : "5" , 
  "livestock" :"{"cow" : "5" , "sheep" :"2" }"
}

有什么想法吗?


你想把数字捕获为字符串有什么原因吗? - kindall
不一定,我想这样做可能会更容易。 - mwaks
这有点矛盾。你不能真正将字符串更改为字典类型... 就像你不能将类型更改为 dict 一样。 这非常有趣,我想找出它的运作方式... JSON 是一种有用的方法,但是采用蛮力硬编码的方式如何? - drewteriyaki
那是一个格式奇怪的字典。它是从哪来的? - kindall
这是来自Mac应用程序的内容。我需要将其转换为真正的Python字典以便更快地访问。 - mwaks
4个回答

23

这个问题在988251中已经解决。 简而言之,使用Python的ast库的literal_eval()函数即可。

import ast
my_string = "{'key':'val','key2':2}"
my_dict = ast.literal_eval(my_string)

1
它可以工作,但要小心,这将改变字典顺序。 - Flavio Pegas
6
请使用@mwaks提供的数据并重试。 - dindom
1
哇,太棒了。谢谢您,先生。 - Ganesan J

6
您输入的字符串存在问题,因为它实际上不是有效的JSON格式,因为您的键没有声明为字符串。否则,您可以使用“json”模块加载它并完成操作。
一个简单而粗略的方法是首先将其转换为有效的JSON格式,即在所有不是空格或语法字符的内容周围添加引号:
source = '{tomatoes : 5 , livestock :{cow : 5 , sheep :2 }}'

output = ""
quoting = False
for char in source:
    if char.isalnum():
        if not quoting:
            output += '"'
            quoting = True
    elif quoting:
        output += '"'
        quoting = False
    output += char

print(output)  #  {"tomatoes" : "5" , "livestock" :{"cow" : "5" , "sheep" :"2" }}

这样可以得到一个有效的JSON,现在您可以使用json模块将其轻松解析为Python dict

import json

parsed = json.loads(output)
# {'livestock': {'sheep': '2', 'cow': '5'}, 'tomatoes': '5'}

为什么要使用JSON?为什么不直接使用parsed = eval(output) - innisfree
1
@innisfree - 因为没有理智的人会使用eval,即使是疯子也应该三思而后行...如果真的找不到其他方法,那么请使用ast.literal_eval()。此外,它比json.loads()慢得多。 - zwer
好的。为什么没有理智的人会使用它? - innisfree
3
请从innsifree - start with Eval really is dangerous开始,然后在此SO上用关键词“eval”和“dangerous”,“bad practice”,“slow”等进行搜索,您会得到超过一大堆的原因,说明为什么不应该使用eval()。简而言之,在99.999%的情况下,存在更快、更好、更安全的解决方案,而不必让您的系统承受运行任意代码的危险。 - zwer
1
你没有将系统暴露给任意代码,而是一个非常特定的代码片段,即'{tomatoes: 5, livestock: {cow: 5, sheep: 2}}' - innisfree
2
@innisfree - 这只是一个例子,OP已经通过提出问题将该字符串转换为所需的任何内容。可以安全地假设它将用于OP无法控制的任意字符串(否则他/她可以强制使用最适合他们的格式),而您不希望eval()接触任意字符串(这就是为什么大多数人都想使用eval())。 - zwer

0
你手头有一个JSON格式的字符串,想要将其转换为Python字典。

使用JSON库:

import json
with open("your file", "r") as f:
    dictionary =  json.loads(f.read());

现在字典包含了你正在寻找的数据结构。


2
请注意,OP的字符串不是有效的JSON。 - chthonicdaemon
键和值没有声明为字符串。 - mwaks

-2

这是我的答案:

dict_str = '{tomatoes: 5, livestock: {cow: 5, sheep: 2}}'

def dict_from_str(dict_str):    

    while True:

        try:
            dict_ = eval(dict_str)
        except NameError as e:
            key = e.message.split("'")[1]
            dict_str = dict_str.replace(key, "'{}'".format(key))
        else:
            return dict_


print dict_from_str(dict_str)

我的策略是通过使用eval将字典str转换为dict。但是,我首先必须处理您的字典键没有用引号括起来的事实。我通过尝试评估它并捕获错误来解决这个问题。从错误消息中,我提取被解释为未知变量的键,并用引号括起来。

我不确定篡改错误信息是愚蠢还是聪明的做法 :D - innisfree
1
人们对于使用 eval 函数往往会感到敏感,但请记住,在 ast 模块中有一个名为 literal_eval 的函数,它的评估范围要小得多,因此更加安全。 - Paul Rooney
@paul 哈哈,是的,我注意到了 ;) - innisfree

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接