【问题标题】:Creating dictionary by reading a file with default values通过读取具有默认值的文件来创建字典
【发布时间】:2015-10-09 06:52:46
【问题描述】:

我必须通过读取文件来创建字典

信息被分成几行

键在括号之间,但并非所有键都是键。只是 [日期] 之后的那些

两个键之间是分成几行的值,但并非所有行都是可选值

最终的结果应该是这样的

d=[键:[单位、高度、场地]]

有些键没有所有的值。然后,如果不存在单位、高度或站点,则该值应使用 '' 或 0

#info in the file
[System]
serial=130204
[Summary]
file_created=2014-11-20 03:02:09
user=j
....#more info
[date]#after this key starts the keys
...
[AX1]
units=m/s
serial_setting=38400
height=70.4
stats=avg
formula=yes
site=site1
[H4]
serial_setting=38100
height=20.6
stats=std
formula=yes
site=site2
[V3]
units=m
...

示例中的最终结果

param={AX1:['m/s',70.4,'site1'],H4:['',20.6,'site2'], V3:['m',0,'']}

我知道如何从列表列表创建字典,但不设置默认值('' 用于字符串值,0 用于数字值)以防某些值丢失

我尝试使用 Collections 中的 defaultdict,但我对这个类还不是很熟悉,可能我没有使用它的所有可能性

感谢您的帮助

【问题讨论】:

    标签: python file dictionary collections


    【解决方案1】:

    这可以使用 Python 的 ConfigParser 来完成,如下所示:

    import ConfigParser
    from itertools import dropwhile
    import io
    
    config = ConfigParser.ConfigParser({'unit' : '', 'units' : '', 'height' : 0, 'site' : ''})
    skip = []
    
    # Skip over lines until the first section is found
    with open('input.txt', 'r') as f_input:
        for line in dropwhile(lambda x: not x.startswith('['), f_input):
            skip.append(line)
    
    config.readfp(io.BytesIO('\n'.join(skip)))      
    
    # Remove sections which are not required
    for remove in ['Summary', 'System', 'date']:
        config.remove_section(remove)
    
    param = {}
    for section in config.sections():
        param[section] = [
            config.get(section, 'unit') + config.get(section, 'units'), 
            config.getfloat(section, 'height'),
            config.get(section, 'site')]
    
    print param
    

    给你输出:

    {'AX1': ['m/s', 70.4, 'site1'], 'V3': ['m', 0.0, ''], 'H4': ['', 20.6, 'site2']}
    

    此外,文件中的行在找到第一部分之前不会被解析,即以 [ 开头的行。

    【讨论】:

    • 这看起来不错,但是如果文件开头有没有标题格式[]的行怎么办。它会生成一个错误“MissingSectionHeaderError:文件不包含节标题。”如何使用 config.read() 从特定行读取?
    • 我已经更新了脚本,现在可以跳过任何非标准的标头信息。它现在应该可以根据需要工作了。
    【解决方案2】:

    在您确定密钥开始的点之后,这应该会为您提供有关如何解析文件其余部分的必要想法:

    defaults = {'units':'', 'height':0, 'site':''}
    
    with open(<file>) as f:
        <skip first section to date>
    
        param = {}
        d = {}
        tag = ""
        for line in f:
            if line[0] == '[':
                if tag:
                    param[tag] = [d.get(k, defaults[k]) for k in ['units', 'height', 'site']]
                tag = line[1:-2]
                d = {}
                continue
            k,v = line.rstrip().split('=')
            d[k] = v
        else:
            param[tag] = [d.get(k, defaults[k]) for k in ['units', 'height', 'site']]
    param
    

    输出(将'AX1'中的unit更改为units):

    {'AX1': ['m/s', '70.4', 'site1'],
     'H4': ['', '20.6', 'site2'],
     'V3': ['m', 0, '']}
    

    更新:我真的很喜欢@MartinEvans 使用 configparser [py3] (ConfigParser [py2]) 的方法,但相信它可以更简单:

    from configparser import ConfigParser
    #from ConfigParser import ConfigParser  [py2]
    
    with open(<file>) as f:
        <skip first section to date>
    
        config = ConfigParser()
        config['DEFAULT'] = {'units':'', 'height':0, 'site':''}
        config.read_file(f)
        # config.readfp(f)  [py2]
        for section in config.sections():
            param[section] = [config.get(section, k) for k in ['units', 'height', 'site']]
    param
    

    输出:

    {'AX1': ['m/s', '70.4', 'site1'],
     'H4': ['', '20.6', 'site2'],
     'V3': ['m', 0, '']}
    

    【讨论】:

      猜你喜欢
      • 2019-05-05
      • 1970-01-01
      • 2011-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-06
      • 2016-06-25
      • 2016-08-26
      相关资源
      最近更新 更多