【问题标题】:Converting string to dict? [duplicate]将字符串转换为字典? [复制]
【发布时间】:2012-11-20 11:41:52
【问题描述】:

我有一个脚本,可以将 dict 更改为字符串并将其保存到文件中。然后我想加载该文件并将其用作字典,但它是一个字符串。是否有类似int("7") 的东西可以将格式化为字典({a: 1, b: 2})的字符串更改为字典?我试过dict(),但这似乎不是它的作用。我听说过一些涉及 JSON 和 eval() 的过程,但我真的不明白这是做什么的。该程序加载它保存的相同数据,如果有人编辑它并且它不起作用,那不是我的问题(我不需要任何高级方法来确认 dict 数据或任何东西)。

【问题讨论】:

  • 如果你想序列化一个dict 为什么不直接使用pickle?
  • 是的,你为什么要这样做?
  • @MatthewAdams 你是什么意思?
  • Pickle 序列化 Python 对象。 @MatteoItalia 指出的是,如果您正在将字典写入文件并需要它们再次成为有效对象,您不妨使用pickle 来简化过渡。
  • 哦,我看错了你的问题。是的,你想序列化字典; pickle 是一种方法。

标签: python string dictionary


【解决方案1】:

试试这个,这是最安全的方法:

import ast
ast.literal_eval("{'x':1, 'y':2}")
=> {'y': 2, 'x': 1}

所有基于eval() 的解决方案都是危险的,恶意代码可能被注入到字符串中并被执行。

根据documentation,表达式得到安全评估。此外,根据source codeliteral_eval 将字符串解析为 python AST(源树),并且仅在它是文字时才返回。代码永远不会被执行,只会被解析,所以没有理由让它成为安全风险。

【讨论】:

  • 我不知道ast 模块,谢谢这个!
  • 为什么这样更安全?是不是很容易出现同样的问题?
  • 哦,找到了答案。这是因为 ast.literal_eval 仅适用于文字。 source
  • @MatthewAdams 根据documentation,表达式得到安全评估。此外,根据sourceliteral_eval 将字符串解析为 python AST(源树),并且仅当它是文字时才返回。代码永远不会被执行,只会被解析,所以没有理由存在安全风险
  • 酷。我知道ast,但我不会想到在这里使用它。 +1
【解决方案2】:

这个格式不是JSON,而是YAML,可以用PyYAML解析:

>>> import yaml
>>> s = '{a: 1, b: 2}'
>>> d = yaml.load(s)
>>> d
{'a': 1, 'b': 2}
>>> type(d)
<type 'dict'>

【讨论】:

  • 这样就成功转换了。在字符串上使用 json 库或 dict() 将失败。谢谢。
  • yaml 技巧不适用于 In [12]: ast.literal_eval(s) Out[12]: {u'username': u'test'} In [13] 之类的 dicts: yaml.load(s) Out[13]: {"u'username'": "u'test'"}
【解决方案3】:

如果您信任输入字符串,您可以使用eval

>>> a=eval('{"a":1,"b":2}')
>>> a
{'a': 1, 'b': 2}

【讨论】:

  • 但是,为了完整起见,需要注意的是,使用eval 通常是个坏主意。
  • 这里ast.literal_eval 就足够了。但是请注意,问题中提到的格式 ({a: 1, b: 2}) 实际上并不是 Python 代码。
  • @tkbx: eval 如果您完全确信输出是安全的,那就没问题了。但是,如果你不这样做,它可能与将数据从在线直接输入命令行一样糟糕 - 例如,如果有人用 os.system 调用交换了预期的输入。
  • @tkbx 哈哈,是的,但是有人可以将您正在读取的文件替换为包含恶意 python 代码的文件,并且您的程序中的 eval 会很高兴地运行它。
  • @tkbx 在这种特定情况下真的很重要吗?可能不是。但原则绝对重要。如果编写 Microsoft Word 的人采用相同的方法会怎样?如果黑客发现他们只需修改一个文件就可以控制系统,那么这会使他们的“工作”变得容易得多。考虑到安全性是很好的编码。
【解决方案4】:

序列化

您所说的是object serialization,并且有比滚动您自己的序列化方法更好的方法(尽管您似乎已经提出了 YAML)。这两种方法仍然不如ast.literal_eval() 方法安全(尤其是pickle),但这里绝对应该注意它们。

JSON

这是一个使用JSON(一种流行的跨语言格式)做你想做的事的例子:

import json

myDict = {'a':1, 'b':2}

# write to the file 'data'
with open('data','w') as f:
    json.dump(myDict, f)

# now we can load it back
with open('data','r') as f:
    myDictLoaded = json.load(f)

print myDictLoaded

输出:

{u'a': 1, u'b': 2}

泡菜

这是使用pickle 执行相同操作的第二个示例。 pickle 更强大,它可以序列化所有* python 对象,甚至是你编写的对象。

import cPickle as pickle

myDict = {'a':1, 'b':2}

# write to the file 'data'
with open('data','w') as f:
    pickle.dump(myDict, f)

# now we can load it back
with open('data','r') as f:
    myDictLoaded = pickle.load(f)

print myDictLoaded

输出:

{'a': 1, 'b': 2}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 2019-11-01
    • 1970-01-01
    • 2021-07-25
    相关资源
    最近更新 更多