用Python从文本/文件创建字典,其中文本/文件的格式为字典格式

32
我想要从一个包含“字典”格式内容的文本文件创建一个字典。这是文件包含内容的样本:

{'fawn': [1], 'sermersheim': [3], 'sonji': [2], 'scheuring': [2]}

它与此完全相同,只不过包含了 125,000 条记录。我可以使用read()方法读取文本文件,但即使我使用以下初始化变量的方式:

dict = {}

它也会创建一个包含文本的变量。

13
ast.literal_eval是一个Python模块中的函数,它可以安全地将字面量字符串转换为对应的Python数据类型。 - JBernardo
1
只要你有Python 2.6或更新版本,@JBernardo +1,这就是正确的方法。ast模块在2.5中被引入,但没有辅助函数(如literal_eval)。这些函数在2.6中出现。 - Steven T. Snyder
6个回答

38

你可以使用内置函数eval。例如,如果每个字典条目占据不同的行,则可以使用以下代码:

dicts_from_file = []
with open('myfile.txt','r') as inf:
    for line in inf:
        dicts_from_file.append(eval(line))    
# dicts_from_file now contains the dictionaries created from the text file

或者,如果该文件只是一个大型字典(即使跨越多行),您可以执行以下操作:

with open('myfile.txt','r') as inf:
    dict_from_file = eval(inf.read())

这可能是最简单的方法,但不是最安全的。正如其他人在他们的答案中提到的那样,eval 存在一些固有的安全风险。正如 JBernardo 提到的那样,替代方案是使用 ast.literal_eval,它比 eval 更安全,因为它只会评估包含文字的字符串。导入 ast 模块后,你可以在上面的示例中将所有对 eval 的调用简单地替换为 ast.literal_eval

如果你正在使用 Python 2.4,你将没有 ast 模块,也没有 with 语句。代码看起来更像这样:

inf = open('myfile.txt','r')
dict_from_file = eval(inf.read())
inf.close()

别忘了调用 inf.close()。使用 with 语句的好处是,即使 with 语句中的代码块引发异常,它也会为您关闭文件。


如果这只是一个大段文字怎么办?它实际上只是一个以 { 开头、以 } 结尾的字符串。 - Jared
你正在使用Python 2.5或更新版本吗? - Steven T. Snyder
@Jared 我编辑了我的答案,包括一些关于使用早于2.5版本的Python的注意事项,似乎你可能正在使用这个版本。基本上,你将没有with语句(不太重要),也没有ast模块。 - Steven T. Snyder
是的,你赢得了Pickle @Series8217。我在这台电脑上有2.4版本,在我的另一台(主要)电脑上有2.5版本,所以我不知道“with”不能工作! - Jared
1
FYI:看起来该方法现在是ast.literal_eval,而不是ast.literaleval - Taylor D. Edmiston
显示剩余3条评论

3

使用 eval 函数。

例如,

dict = eval(open("yourfile.txt").read())

1
+1 eval 确实是最简单的方法。但是 @JBernardo 提到的 ast.literal_eval 更安全,因为它只允许字符串、数字、元组、列表、字典、布尔值和 None。这是需要考虑的事情。 - istruble

3

eval的使用可能是危险的。如果json无法正常工作,我建议使用yaml,这似乎可以很好地处理您的示例输入:

>>> import yaml
>>> yaml.load("{'fawn': [1], 'sermersheim': [3], 'sonji': [2], 'scheuring': [2]}")
{'fawn': [1], 'scheuring': [2], 'sermersheim': [3], 'sonji': [2]}

啊,我想使用它,但是我没有这个模块,而且代码运行的系统没有互联网访问权限。无论如何还是谢谢! - Jared
你可能想考虑从源代码安装。根据文档,这应该很容易:python setup.py install - jcollado

2

这不是一个可用于生产环境的解决方案,可能无法很好地处理您的文件大小,但如果您需要一种简单的方法并且能够在您的文件前添加内容,则可以使用它。

my_dict = {'fawn': [1], 'sermersheim': [3], 'sonji': [2], 'scheuring': [2]}

然后你可以将它重命名为Python文件,然后简单地导入。
from my_file import my_dict 

1

我强烈不建议使用eval。如果您无法完全控制输入文件,可能会导致安全问题。只需导入您的字典并使用jsonpickle模块保存它们。


我同意如果在常规基础上或生产代码中使用eval,它是一个巨大的安全风险,但我理解原始问题是处理来自可信源并已经在文本文件中的孤立代码。在这种情况下,你没有太多其他选择。 - user457586
它来自可信源的静态文件,是的! - Jared
我在pickle文件方面运气不佳。我有一个.pickle文件中包含相同的信息,但似乎无法加载回来。此代码正在没有互联网访问权限的受限系统上运行。 - Jared
@Jared 或许你应该发一个关于你在使用pickle时遇到问题的提问,因为那似乎是真正的问题所在。 - jcollado

0

这看起来像是json。如果是的话,可以使用json模块。

这看起来像是yaml。如果是的话,可以使用pyyaml模块。(由@jcollado建议)。

你不能使用json模块,因为它对输入要求严格。


4
这不是 JSON,它使用单引号而不是双引号。 - Ned Batchelder
@NedBatchelder:是的。我没有意识到json模块对其输入有严格要求。 - Marcin

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