Python:文本文件到字典,同时保留顺序?

时间:2014-01-05 02:46:16

标签: python file dictionary eval

我有一个包含以下内容的文本文件:

{'InventoryTake':'Key','OtherSceneNode':'Shed','AddOtherScene':'ShedOpen'}

从文本文件中检索数据的代码:

    readin = eventVar.readline()
    Results = eval(readin)

我遇到的问题是,由于运行代码的性质,我需要保持字典顺序。但是python以随机顺序存储字典键。

我尝试使用有序词典来保存订单,但这没有什么区别。我认为这是因为当有序字典获取信息时,它已经按照从文件中读取的内容进行排序。

我已经尝试使用eval,literal_eval和json解析器来正确读取数据,但是在运行程序时字典总是以错误的顺序出现。

该程序的这一部分的目的是允许文本文件字典尽可能多地存储这些对(OtherSceneNode和AddOtherScene / TakeOtherScene)。所以我不能假设只有一组这些键值对。

我正在使用python 2.7.5,如果它有助于它出现的顺序是:

{'InventoryTake':'Key','AddOtherScene':'ShedOpen','OtherSceneNode':'Shed'}

我可以重做文本文件以获取特定的行,但这会使我的文本文件更复杂,我觉得它只是避免问题而不是解决问题。

3 个答案:

答案 0 :(得分:1)

一种方法是在字符串中查找已解析的数据对以查找其原始相对顺序:

line = "{'InventoryTake':'Key','OtherSceneNode':'Shed','AddOtherScene':'ShedOpen'}"
data = eval(line)
sorted(data.items(), key=lambda pair: line.index("'%s','%s'" % pair)

给了我:

[('InventoryTake', 'Key'),
('OtherSceneNode', 'Shed'),
('AddOtherScene', 'ShedOpen')]

答案 1 :(得分:1)

这应该可以解决问题,并且比大多数其他解决方案都短。

from collections import OrderedDict

data = []
for line in eventVar.readline():
    # Remove braces
    line = line.strip()[1:-1]
    results = OrderedDict()
    # Split by comma sign
    for pair in line.split(','):
        # Get key and value by splitting on colon
        key, value = pair.split(':')
        # Use eval to get rid of quotation surrounding the key and value
        results[eval(key)] = eval(value)
        # Add the results from reading this line to a list
        data.append(results)

答案 2 :(得分:0)

这有点罗嗦,但似乎做了你要求的事情:

#!/usr/local/cpython-3.3/bin/python

import shlex
import collections

def strip_single_quote(string):
    assert string[0] == "'"
    assert string[-1] == "'"
    return string[1:-1]

def dict_to_tuples(string):
    list_ = list(shlex.shlex(string))
    assert list_[0] == '{'
    assert list_[-1] == '}'
    list_ = list_[1:-1]
    print(list_)
    len_list = len(list_)

    for base_index in range(0, len_list, 4):
        assert list_[base_index + 1] == ':'
        if list_[base_index + 3:]:
            assert list_[base_index + 3] == ','
        key = strip_single_quote(list_[base_index + 0])
        value = strip_single_quote(list_[base_index + 2])
        yield (key, value)

def main():
    string = "{'InventoryTake':'Key','OtherSceneNode':'Shed','AddOtherScene':'ShedOpen'}"
    od = collections.OrderedDict(dict_to_tuples(string))
    print(od)