2012-06-05 4 views
0

여기에 주니어 파이썬 프로그래머가 있습니다. 예기치 않은 루프 및 사전 동작에서 벽돌 벽에 머리를 때리고 있습니다. 내가 로그 항목의 CSV 파일을 통해 루핑하고 카테고리 dict에 데이터를 구문 분석하고있어. 나는 범주는 루프를 통해 각 시간을 DICT 초기화하면 예상대로 작동합니다 .. 그래서 같이dict 변수 & for for loop with Python

:

이보기에서
log_entries = AutoVivification() 
# http://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries-in-python 

def scrublooper(log_file): 

    for ll in log_file: 
    # Initialize categories dict every round through the loop 
    categories = {'requests': {'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 0, 'Pages': 0, 'Content_Files': 0}, 'filter_action': {'re': 0, 'pl': 0, 'bs': 0}} 
    lld = LogDomain(ll) 
    domain, hostname, lan_host = lld.domain, lld.hostname, lld.lan_host 


    mimetypes = url_searcher(Settings.mimetypes, lld.mime_type) 

    if mimetypes: 
     category = mimetypes[2] 

     if not log_entries[lan_host].has_key(domain): 
      log_entries[lan_host][domain]= categories 

     log_entries[lan_host][domain]['requests'][category] += 1 

print log_entries['192.168.5.210']['google.com']['requests'] 
print log_entries['192.168.5.210']['webtrendslive.com']['requests'] 
print log_entries['192.168.5.210']['osnews.com']['requests'] 
print log_entries['192.168.5.210']['question-defense.com']['requests'] 
print log_entries['192.168.5.210']['optimost.com']['requests'] 

출력 내가 기대하는 것입니다 그러나

{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 95, 'Pages': 0, 'Content_Files': 0} 
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 1, 'Pages': 0, 'Content_Files': 0} 
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 2, 'Pages': 0, 'Content_Files': 0} 
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 18, 'Pages': 0, 'Content_Files': 0} 
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 3, 'Pages': 0, 'Content_Files': 0} 

! 여기 내 문제가있다. 루프를 통해 매순간 범주를 초기화하지 않으려합니다. 이 단순화 된 예제에서는 중요하지 않지만이 프로그램의 길 아래에서 성능이 크게 저하됩니다 (30 %). I 초기화시 카테고리가 루프합니다 (scrublooper 함수인지 단순히 오른쪽 변수 log_entries 후) 출력 외부를 딕셔너리,

log_entries = AutoVivification() 
categories = {'requests': {'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 0, 'Pages': 0, 'Content_Files': 0}, 'filter_action': {'re': 0, 'pl': 0, 'bs': 0}} 

def scrublooper(log_file): 

    for ll in log_file: 
    lld = LogDomain(ll) 
    # etc, etc, etc 

을 그러나 :

난 딕셔너리 ONCE 범주를 초기화해야 is :

{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0} 
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0} 
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0} 
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0} 
{'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text': 685, 'Pages': 0, 'Content_Files': 0} 

모든 'Conent_Text'값이 동일하게 증가했습니다. 여기서 무슨 일이 일어나고있는거야? 나는 파이썬 원칙을 어겨 봤지만 무엇을 어떻게 찾을 지 모른다. 문제가 범주 dict에 연결되어 있다는 것을 알아내는 데는 시간이 걸렸습니다.

설명이 필요합니다.

+0

그렇다면'categories'는 실제로 어디에서 조작되고 있습니까? 나는 단지 그것이 초기화되고 읽혀지는 것을 본다. 네가 이것을 너무 단순화 시켰 니? –

+0

너무 단순화 된 것 같지 않습니다. 항상 배정되고 절대로 조작되지 않습니다. 'log_entries' dict 키/값에 할당 :'log_entries [lan_host] .has_key (domain) :''log_entries [lan_host] [domain] = categories' – Thinkwell

답변

2

저는 사용하는 도구에 익숙하지 않지만 루프 외부에서 사전을 만들 때 하나의 사전 만 만들고 있습니다.

if not log_entries[lan_host].has_key(domain): 
     log_entries[lan_host][domain]= categories 

이 코드는 단지 하나의 사전에 log_entries [lan_host] [도메인] 포인트를합니다. 파이썬은 값이나 그런 것을 복사하지 않습니다. 그래서이 라인들은 같은 사전을 참조합니다.

log_entries['192.168.5.210']['google.com'] 
log_entries['192.168.5.210']['webtrendslive.com'] 

P. 나는 확실히 말할 수는 없지만, 나의 직감은 성능을 위해 새 사전을 초기화하고 싶지 않은 것은 아마도 과도하다고 말합니다.

+0

음, 음, 좋아 ... 'log_entries [lan_host] [domain]'dict를'categories' 사전 구조를 포함하도록 확장 한 다음'log_entries' 인스턴스를 조작하십시오. 어떻게 코드를 변경하여 만들 수 있습니까? (Autovivification 함수는 존재하지 않는 키를 자동으로 추가합니다. 변수를 참조하는 대신'categories' 구조체를 추가하는 것으로 생각했습니다). – Thinkwell

+0

좋아, 내가 바꿀 때 :'log_entries [lan_host] [domain] = categories''log_entries [lan_host] [domain] = { 'requests': { 'Content_Visual': 0, 'Content_ProgramsUpdates': 0, 'Content_Text' : 0, '페이지': 0, 'Content_Files': 0}, 'filter_action': { 're': 0, 'pl': 0, 'bs': 0}}'그러면 작동합니다. 그래서 분명히 내 코드는 DICT를 확장하는 대신'categories' 변수를 참조하고있었습니다. 그러나 사전 대신 변수 구문을 사용해야합니다. 나는 구문을 실험 할 필요가 있다고 생각한다. – Thinkwell

+0

내가 분명해야 했어. 루프 안에 사전을 만들면 매번 새로운 사전이 만들어집니다. 각 log_entries [lan_host] [domain]은 고유합니다. 이것이 코드를 올바르게 작동시키는 이유입니다. –