2013-10-26 62 views
1

我有一些代碼來解析Apache日誌文件(start_searchend_search是在Apache日誌中找到的格式的日期字符串):爲什麼我不能分割這個python列表?

with open("/var/log/apache2/access.log",'r') as log: 
    from itertools import takewhile, dropwhile 
    s_log = dropwhile(lambda L: start_search not in L, log) 
    e_log = takewhile(lambda L: end_search not in L, s_log) 
    query = [line for line in e_log if re.search(r'GET /(.+veggies|.+fruits)',line)] 

    import csv 
    query_dict = csv.DictReader(query,fieldnames=('ip','na-1','na-2','time', 'zone', 'url', 'refer', 'client'),quotechar='"',delimiter=" ") 

    import re 
    veggies = [ x for x in query_dict if re.search('veggies',x['url']) ] 
    fruits = [ x for x in query_dict if re.search('fruits',x['url']) ] 

第二列表生成總是空的;也就是說,如果我切換最後兩行的順序:

fruits = [ x for x in query_dict if re.search('fruits',x['url']) ] 
    veggies = [ x for x in query_dict if re.search('veggies',x['url']) ] 

第二個列表總是空的。

爲什麼? (以及如何填充fruitsveggies列表?)

+1

調用它'query_dict'不會使它成爲'dict'。 – kindall

+0

@kindall也許更有建設性的評論會是''csv.DictReader'不返回列表字典,而是一個迭代器「。 – Jamie

回答

7

您只能遍歷迭代器一次; query_dict是一次迭代器,一旦對veggies進行掃描,就不能再次迭代以搜索fruits

不要在這裏使用列表解析。遍歷query_dict一次,檢查兩個veggiesfruits每個條目:

veggies = [] 
fruits = [] 

for x in query_dict: 
    if re.search('veggies',x['url']): 
     veggies.append(x) 
    if re.search('fruits',x['url']): 
     fruits.append(x) 

的替代方案將是:

  • 重建csv.DictReader()對象爲fruits列表:

    query_dict = csv.DictReader(query,fieldnames=('ip','na-1','na-2','time', 'zone', 'url', 'refer', 'client'),quotechar='"',delimiter=" ") 
    veggies = [ x for x in query_dict if re.search('veggies',x['url']) ] 
    query_dict = csv.DictReader(query,fieldnames=('ip','na-1','na-2','time', 'zone', 'url', 'refer', 'client'),quotechar='"',delimiter=" ") 
    fruits = [ x for x in query_dict if re.search('fruits',x['url']) ] 
    

    這是雙重工作;您遍歷整個數據集兩次。

  • 使用itertools.tee(),以「克隆」的迭代器:

    from itertools import tee 
    veggies_query_dict, fruits_query_dict = tee(query_dict) 
    veggies = [ x for x in veggies_query_dict if re.search('veggies',x['url']) ] 
    fruits = [ x for x in fruits_query_dict if re.search('fruits',x['url']) ] 
    

    這結束了緩存所有的query_dicttee緩衝,需要兩次爲同一任務的記憶,直到fruits再次清空了緩衝區。

+0

感謝您的解釋;超級讚賞。 – Jamie

相關問題