Python中的字符串转换为有序字典

4
我使用 collections 库创建了一个 Python 有序字典,并将其存储在一个名为 "filename.txt" 的文件中。该文件的内容如下:
OrderedDict([(7, 0), (6, 1), (5, 2), (4, 3)])

我需要在另一个程序中使用这个OrderedDict。我的做法是:

myfile = open('filename.txt','r')
mydict = myfile.read()

我需要将'mydict'作为类型获取

<class 'collections.OrderedDict'>

但是在这里,它变成了 'str' 类型。
在 Python 中有没有一种将字符串类型转换为 OrderedDict 类型的方法?使用的是 Python 2.7。


我没有一个好的答案(即不使用eval)来回答你的问题,但你确实不应该这样存储它。 - jamylak
不要那样存储你的数据。至少使用Pickle。我会对任何建议使用eval()的答案进行投反对票。 - John La Rooy
人们害怕使用 eval 的原因本质上是出于信仰而非理性。每种语言结构都有其存在的理由,当一个简单的 eval(x) 就能解决问题时,没有必要发明一些复杂的东西。是的,它应该谨慎使用(就像任何其他东西一样),但只要数据来自可信的来源,使用 eval 是完全可以的。 - georg
@thg435 嗯,既然我们不知道数据是否来自可信源,那么这是一个重要的步骤。即使如此,为什么要使用丑陋、缓慢、可能危险、难以调试的方法,当有更好的方法呢?真正的问题在于数据的存储方式,将其存储在另一种格式中还有其他优点(比如如果你需要将数据转换成Python之外的格式怎么办?)。 - Gareth Latty
@Lattyware:评估辩论已经说烦了。就像几十年前的“goto”一样,人们似乎对它产生了某种非理性的恐惧。我们大多数人认为它本质上是邪恶的,并相信仅仅写一次就会给他们的代码甚至生命带来永恒的诅咒。这似乎是某种宗教信仰,因此在计算机编程的理性世界中没有任何业务。 - georg
显示剩余3条评论
4个回答

7
你可以使用pickle来存储和加载它。
import cPickle as pickle

# store:
with open("filename.pickle", "w") as fp:
    pickle.dump(ordered_dict, fp)

# read:
with open("filename.pickle") as fp:
    ordered_dict = pickle.load(fp)

type(ordered_dict) # <class 'collections.OrderedDict'>

7
注意,腌制食品和eval函数一样危险。不要反序列化你不能信任的数据。 - John La Rooy
@gnibbler:提到pickle不安全,点赞。另外请参考:http://nadiana.com/python-pickle-insecure - rubik

6
这里最好的解决方案是以不同方式存储数据。例如,将其编码为JSON

你也可以使用pickle模块,如其他答案所述,但这可能存在安全问题(如下所述的eval()) - 因此只有在您知道数据始终可信时才使用此解决方案。

如果无法更改数据格式,则还有其他解决方案。

真正糟糕的解决方案是使用{{link3:eval()}}来做到这一点。这是一个非常糟糕的主意,因为它是不安全的,因为文件中放置的任何代码都将运行,以及其他原因

更好的解决方案是手动解析文件。优点是有一种方法可以简单地作弊并更轻松地完成它。Python具有ast.literal_eval(),它允许您轻松解析字面量。虽然这不是一个字面量,因为它使用OrderedDict,但我们可以提取列表字面量并解析它。
例如:(未经测试)
import re
import ast
import collections

with open(filename.txt) as file:
    line = next(file)
    values = re.search(r"OrderedDict\((.*)\)", line).group(1)
    mydict = collections.OrderedDict(ast.literal_eval(values))

1
如果有以下两点,那么评分会是+2而不是+1:a)可能性,b)更清楚地标明“真正糟糕的解决方案”实际上是“纯恶”。 - Chris Pfohl
当前问题的解决方案不错,我也在考虑同样的事情。 - jamylak
2
@Cpfohl,c)如果+2是可能的 - John La Rooy
1
@gnibbler:看看 a ;-)...哎呀...语法错误 1450 模糊解析。 - Chris Pfohl
@thg435,“eval没有任何问题”这种说法是错误的——它是一种可怕的完成任务的方式,而且有更好的方法来解决问题。在我的回答中,我提供了两种好的方法。评论仅仅指出eval不会毁掉整个世界,但并证明它是安全的,或者是解决此类问题的好方法。 - Gareth Latty
显示剩余4条评论

0

这不是一个好的解决方案,但它能够工作。:)

#######################################
# String_To_OrderedDict
# Convert String to OrderedDict
# Example String
#    txt = "OrderedDict([('width', '600'), ('height', '100'), ('left', '1250'), ('top', '980'), ('starttime', '4000'), ('stoptime', '8000'), ('startani', 'random'), ('zindex', '995'), ('type', 'text'), ('title', '#WXR#@TU@@Izmir@@brief_txt@'), ('backgroundcolor', 'N'), ('borderstyle', 'solid'), ('bordercolor', 'N'), ('fontsize', '35'), ('fontfamily', 'Ubuntu Mono'), ('textalign', 'right'), ('color', '#c99a16')])"
#######################################
def string_to_ordereddict(txt):

    from collections import OrderedDict
    import re

    tempDict = OrderedDict()

    od_start = "OrderedDict([";
    od_end = '])';

    first_index = txt.find(od_start)
    last_index = txt.rfind(od_end)

    new_txt = txt[first_index+len(od_start):last_index]

    pattern = r"(\(\'\S+\'\,\ \'\S+\'\))"
    all_variables = re.findall(pattern, new_txt)

    for str_variable in all_variables:
        data = str_variable.split("', '")
        key = data[0].replace("('", "")
        value = data[1].replace("')", "")
        #print "key : %s" % (key)
        #print "value : %s" % (value)
        tempDict[key] = value

    #print tempDict
    #print tempDict['title']

    return tempDict

0

这是我在Python 2.7上的做法

from collections import OrderedDict
from ast import literal_eval

# Read in string from text file
myfile = open('filename.txt','r')
file_str = myfile.read()

# Remove ordered dict syntax from string by indexing
file_str=file_str[13:]
file_str=file_str[:-2]

# convert string to list
file_list=literal_eval(file_str)

header=OrderedDict()
for entry in file_list:
    # Extract key and value from each tuple
    key, value=entry
    # Create entry in OrderedDict
    header[key]=value

再次强调,你应该以不同的方式编写文本文件。


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