【问题标题】:Parsing a datafile in python (2.5.2)在 python (2.5.2) 中解析数据文件
【发布时间】:2009-12-17 15:17:10
【问题描述】:

我有一个像这样的消息定义文件

struct1 
{
  field="name" type="string" ignore="false"; 
  field="id" type="int" enums=" 0="val1" 1="val2" ";
}

struct2
{
  field = "object" type="struct1";
  ...
}

如何将其解析为带有键 'struct1, struct2' 的字典,并且值应该是字典列表,每个字典对应于相应的行号,以便我可以执行以下操作

dict['struct1'][0]['type'] // Would return 'string'
dict['struct1'][1]['type'] // Would return 'int'
dict['struct1'][1]['enums']['0'] // Would return 'val1'
dict['struct2'][0]['type'] // Would return 'struct1'

等等..

另外,我可以更改定义文件的格式,如果你们有任何关于修改定义文件格式以使其更易于解析的建议,请告诉我。

谢谢

【问题讨论】:

    标签: python parsing dictionary


    【解决方案1】:

    我可以推荐YAML吗?恕我直言,数据输入的语法更具可读性,然后您不必编写和维护解析器。避开 XML——它适合标记文本,但不适合数据输入,因为文本不适合人类阅读,到处都有重复的标签。

    【讨论】:

    • 上述 2 结构的 YAML 文件格式是什么?你能举个例子吗?
    【解决方案2】:

    请改用YAML。 python 有PyYAML 库。它被 Google AppEngine 大量使用。

    这只是一个友好的建议:-)

    示例(将标量映射到序列):

    american:
      - Boston Red Sox
      - Detroit Tigers
      - New York Yankees
    national:
      - New York Mets
      - Chicago Cubs
      - Atlanta Braves
    

    当然还有 JSON,它对 Python 有充分的支持(但往往会更伤我的手指 ;-)

    【讨论】:

      【解决方案3】:

      使用可以使用json 作为文件格式,它支持(在python 术语中)字典和列表。由于 json 支持仅适用于 python 2.6 及更高版本,因此您需要此库:http://pypi.python.org/pypi/simplejson/2.0.9

      { "struct1" 
          [
              {"field" : "name", "type" : "string", "ignore" : false },
              {"field" : "id", "type" : "int", "0" : "val1", "1" : "val2" }
              {"field" : "id", "type" : "int", "enums" : { "0": "val1", "1": "val2"}}
          ]
        "struct2"
          [ ... ]
      }
      

      python 部分(草图,未测试):

      >>> import simplejson as json
      >>> d = json.loads(yourjsonstring)
      >>> d['struct1'][0]['field']
      name
      >>> d['struct1'][2]['enums']['0']
      val1
      ...
      

      【讨论】:

      • 如何编写嵌套字典部分?就像我希望枚举作为第二行中的字典
      • 我喜欢这个答案,所以点赞,但我发现我无法在生产环境中安装插件,所以无法使用此方法。
      【解决方案4】:

      我会简单地使用 Python 作为消息定义文件格式。

      让你的消息定义文件是一个普通的 Python 文件:

      # file messages.py
      messages = dict(
          struct1=[
              dict(field="name", type="string", ignore=False),
              dict(field="id", type="int", enums={0: "val1", 1: "val2"}),
              ],
          struct2=[
              dict(field="object", type="struct1"),
              ]
          )
      

      然后您的程序可以直接导入和使用该数据结构:

      # in your program
      from messages import messages
      print messages['struct1'][0]["type"]
      print messages['struct1'][1]['type']
      print messages['struct1'][1]['enums'][0]
      print messages['struct2'][0]['type']
      

      使用这种方法,您可以让 Python 为您进行解析。

      而且你也获得了很多可能性。例如,假设您(出于某种奇怪的原因)有一个包含 1000 个名为“field_N”的字段的消息结构。使用传统的文件格式,您将不得不添加 1000 行字段定义(除非您在配置文件解析器中构建一些循环 - 无论如何,您都在创建编程语言的路上)。为此目的使用 Python,您可以执行以下操作:

      messages = dict(
          ...
          strange_msg=[dict(field="field_%d" % i) for i in range(1000)],
          ...
          )
      

      顺便说一句,在 Python 2.6 上,使用命名元组而不是 dict 是一种选择。或者使用众多可用的“Bunch”类(请参阅 Python 食谱以了解 2.5 的命名元组)。

      编辑:

      下面是读取命令行中指定的消息定义文件的代码。它使用execfile 而不是import

      # file mainprogram.py
      
      def read_messages_from_file(filename):
          module_dict = {}
          execfile(filename, module_dict)
          return module_dict['messages']
      
      if __name__ == "__main__":
          from pprint import pprint
          import sys
      
          for arg in sys.argv[1:]:
              messages = read_messages_from_file(arg)
              pprint(messages)
      

      执行:

      $ python mainprogram.py messages1 messages2 messages3
      

      将读取并打印每个文件中定义的消息。

      【讨论】:

      • 如果我说 3 个单独的文件,我在编写脚本时不知道它们的名称。我希望将文件名作为参数传入。那要怎么做呢?
      • 我可以看到其中的优势,但感觉很糟糕,就像巨大的安全风险一样。或者你的代码有机会神奇地搞砸了。我不确定这是否有意义。
      • 如果您认为这是一个安全风险,您应该问自己的第一件事是:谁会在消息定义文件中添加一些恶意代码。找到那个人并摆脱他。如果他存在,是什么阻止他编辑程序本身?
      • @Jaelebi:使用运行时指定的读取文件信息编辑了答案。
      【解决方案5】:

      Pyparsing 是一个很好用的库。那是我会用的。

      http://pyparsing.wikispaces.com/

      【讨论】:

      【解决方案6】:

      由于您可以随意更改文件格式,因此您可以将其更改为具有可读写 Python 库的多种格式中的任何一种。例如 JSON、YAML、XML,甚至是内置的ConfigParser

      [struct1]
      field: name
      type: string
      ignore: false
      # etc.
      

      【讨论】:

        猜你喜欢
        • 2015-02-14
        • 2011-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多