2015-01-04 2 views
2

내부 프로젝트의 일부로 DNS 영역 파일 레코드를 구문 분석해야합니다. 이 파일은 대략 이와 비슷합니다.구성에서 사전 사전을 만드는 Python

$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은 어디 언급 $의 TTL이 없기 때문에

test-qa  CNAME test-qa.0001.test.domain.com. 

3600의 TTL을 가지고, 위의 데이터, 즉, 3600이다. 그러나

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 
같은 것을 볼 필요가

여기서 내가 뭘 잘못하고 있니?

답변

2

문제의 세부 사항을 살펴보기 전에 오류를 찾기 쉽도록이 코드에서 정리할 수있는 몇 가지 사항이 있습니다. 코드 품질 가이드 라인을 따르면 코드를보다 쉽게 ​​유지하고 이해할 수 있습니다. 특히 변수 이름은 항상 설명 적이어야하며 변수가 무엇을 나타낼 것인지 독자에게 알려야합니다. 나쁜 변수 이름은 독자에게 무엇이 포함되어 있는지 알려주지 않으며, 끔찍한 변수 이름은 변수에없는 변수가 있음을 독자에게 알립니다.

여기에 default_ttl이라는 변수가 있습니다. 일반 독자는이 변수가 항상 기본 ttl을 포함한다고 가정 할 수 있지만 위의 코드 샘플에서는 소스 데이터에 ttl이 지정 되 자마자 변수를 덮어 씁니다.

default_ttl = line 

그것은 코드의 상단에 기본 TTL을 지정하고라는 변수에이 값을 할당 사용하는 많은 명확하게 수도, 말 : current_ttl, 새로운 원점이 발생 될 때마다.

그래서 파일의 상단에 우리는 것 :

DEFAULT_TTL = '$TTL 3600' 

그리고 새로운 원산지가 발생 될 때마다, 현재 TTL은 기본값으로 재설정됩니다.특정 TTL은 소스 데이터에서 발생하는 경우

if origin.search(line): 
      line = line.replace("$ORIGIN ", "") 
      current_ttl = DEFAULT_TTL 

는, 적절한 값이 당시 TTL에 할당 될 수있다 :이 변경 될 때

elif ttl.search(line): 
     current_ttl = line 

되면, 코드의 아래쪽 두 줄 될 것 :

data_dict[primary_key] = [current_ttl] 
data_dict[primary_key][current_ttl] = value 

오류의 원인은 정확히 하나 개의 항목이 포함 된 목록을 작성하는 것으로합니다 - current_ttl을 것을 포함하는 data_dict 사전에 항목을 작성 명부.

다음 줄에서 목록을 사전에서 가져 와서 current_ttl 색인을 사용하여 액세스하십시오. current_ttl은 문자열을 포함하고 목록은 정수를 사용하여 액세스 할 수 있습니다. 인터프리터는 이것을 간단히 요약 한 오류 메시지를 표시합니다! 우리가 아직없는 data_dict의 키를 참조하려고 할 때마다, 그래서 지금

from collections import defaultdict 
data_dict = defaultdict(dict) 

: 코드, 빠른 정리에 큰 수정없이

는 최고 수준의 data_dict에 대한 defaultdict를 사용하는 것입니다 존재한다면, 새로운 빈 사전은 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 
1

오류의 선은

data_dict[primary_key][default_ttl] = value 

때문에입니다 data_dict[primary_key]은 목록이며 사전 개체가 아닙니다. 이 문제를 해결할 수 있습니다.

data_dict[primary_key] = {default_ttl: value} 
관련 문제