Python从配置创建字典的字典

Python从配置创建字典的字典,python,dictionary,data-structures,Python,Dictionary,Data Structures,作为内部项目的一部分,我必须解析dns区域文件记录。该文件大致如下所示 $ORIGIN 0001.test.domain.com. test-qa CNAME test-qa.0001.test.domain.com. $ORIGIN test-qa.domain.com. unit-test01 A 192.168.0.2 $TTL 60 ; 1 minute integration-test A 192.168

作为内部项目的一部分,我必须解析dns区域文件记录。该文件大致如下所示

    $ORIGIN 0001.test.domain.com.
    test-qa     CNAME   test-qa.0001.test.domain.com.
    $ORIGIN test-qa.domain.com.
    unit-test01     A   192.168.0.2
    $TTL 60 ; 1 minute
    integration-test    A   192.168.0.102
    $ORIGIN dev.domain.com.
    web     A       192.168.10.10
    $TTL 300; 5 minutes
    api     A   192.168.10.13
默认ttl为3600,即对于上述数据

test-qa     CNAME   test-qa.0001.test.domain.com. 
它的ttl为3600,因为在任何地方都没有提到$ttl。但是,

unit-test01     A   192.168.0.2 
具有3600的ttl和

integration-test    A   192.168.0.102
具有60秒的ttl

我正试图用上面的数据创建一个数据结构,我想字典可能是遍历这些数据的最佳方式

我所做的:

origin = re.compile("^\$ORIGIN.*")
ttl = re.compile("^$TTL.*")
default_ttl = "$TTL 3600"
data_dict = {}
primary_key = None
value = None
for line in data_zones:
    if origin.search(line):
            line = line.replace("$ORIGIN ", "")
            primary_key = line
    elif ttl.search(line):
            default_ttl = line
    else:
            value = line
    data_dict[primary_key] = [default_ttl]
    data_dict[primary_key][default_ttl] = value
我想把它转换成字典,但我得到了错误

TypeError: list indices must be integers, not str
我的示例数据结构需要如下所示

0001.test.domain.com.: #This would be the first level Key
    ttl:3600: #This would be the second level key
        test-qa     CNAME   test-qa.0001.test.domain.com. #Value

test-qa.domain.com.: #This would be the first level Key
    ttl:3600: #This would be the second level key
        unit-test01     A   192.168.0.2 #value
    ttl:60: #This would be the second level key
        integration-test     A  192.168.0.102 #value

我在这里做错了什么?

在我们研究问题的细节之前,在这段代码中有一些东西可以被清除,从而使错误更容易被发现。遵循代码质量准则可以使代码更易于维护和理解,特别是变量名应该始终是描述性的,并告诉读者变量将代表什么。一个坏的变量名不会告诉读者它包含什么,一个糟糕的变量名会告诉读者这个变量包含它不包含的东西

这里有一个名为default\u ttl的变量。一个偶然的读者可能会假设这个变量总是包含默认的ttl,但是在上面的代码示例中,一旦在源数据中指定了ttl,这个变量就会被覆盖

default_ttl = line
如果在代码顶部指定一个默认TTL,然后在遇到新原点时使用将该值赋给一个名为current_TTL的变量,可能会更清楚

因此,在文件的顶部,我们将有:

DEFAULT_TTL = '$TTL 3600'
每次遇到新原点时,当前ttl都会重置为默认值

if origin.search(line):
            line = line.replace("$ORIGIN ", "")
            current_ttl = DEFAULT_TTL
当源数据中遇到特定的TTL时,可以为当前TTL分配适当的值:

elif ttl.search(line):
        current_ttl = line
一旦进行此更改,代码的最后两行将变为:

data_dict[primary_key] = [current_ttl]
data_dict[primary_key][current_ttl] = value
错误的原因是您正在创建一个只包含一个条目的列表-当前的\u ttl,并在包含该列表的数据字典中创建一个条目

在下一行,您从字典中获取列表,并尝试使用索引current\u ttl访问它。当前ttl包含一个字符串,只能使用整数访问列表。解释器会给你一条错误消息,简洁地总结了这一点

在不对代码进行重大修改的情况下,最快的清理方法是对顶级数据使用defaultdict:

from collections import defaultdict
data_dict = defaultdict(dict) 
现在,每当我们试图引用data_dict中不存在的键时,defaultdict对象将为我们创建一个新的空字典,并在我们试图访问的键处插入data_dict

线路

data_dict[primary_key] = [default_ttl]
现在是多余和不必要的,可以从代码中完全删除它,留下:

from collections import defaultdict
origin = re.compile("^\$ORIGIN.*")
ttl = re.compile("^$TTL.*")
DEFAULT_TTL = "$TTL 3600"
data_dict = defaultdict(dict)
primary_key = None
value = None
for line in data_zones.split('\n'): #Split by line not character
    if origin.search(line):
                line = line.replace("$ORIGIN ", "")
                current_ttl = DEFAULT_TTL
                primary_key = line
    elif ttl.search(line):
            current_ttl = line
    else:
            value = line
    data_dict[primary_key][current_ttl] = value
误差线是

data_dict[primary_key][default_ttl] = value
因为
data\u dict[primary\u key]
是一个列表而不是字典对象。您可以通过执行以下操作来解决此问题

data_dict[primary_key] = {default_ttl: value}