I have an school assignment where I were tasked with writing a apache log parser in Python. This parser will extract all the IP addresses and all the HTTP Methods using Regex and store these in a nested dictionary. The code can be seen below:
def aggregatelog(filename): keyvaluepairscounter = {"IP":{}, "HTTP":{}} with open(filename, "r") as file: for line in file: result = search(r'(d{1,3}.d{1,3}.d{1,3}.d{1,3})s*.*"(b[A-Z]+b)', line).groups() #Combines the regexes: IP (d{1,3}.d{1,3}.d{1,3}.d{1,3}) and HTTP Method ("(b[A-Z]+b)) if result[0] in set(keyvaluepairscounter["IP"].keys()): #Using set will lower look up time complexity from O(n) to O(1) keyvaluepairscounter["IP"][result[0]] += 1 else: keyvaluepairscounter["IP"][result[0]] = 1 if result[1] in set(keyvaluepairscounter["HTTP"].keys()): keyvaluepairscounter["HTTP"][result[1]] += 1 else: keyvaluepairscounter["HTTP"][result[1]] = 1 return keyvaluepairscounter
This code works (it gives me the expected data for the log files we were given). However, when extracting data from large log files (in my case, ~500 MB) the program is VERY slow (it takes ~30 min for the script to finish). According to my teacher, a good script should be able to process the large file in under 3 minutes (wth?). My question is: Is there anything I can do to speed up my script? I have done some things, like replacing the lists with sets which have better lookup times.
Advertisement
Answer
I found my answer. Use “re.findall()” instead of storing returned regex data in array as such:
for data in re.findall(pattern, text): do things
instead of
array = re.findall(pattern, text) for data in array: do things
I also read the entire file in one go:
file = open("file", "r") text = file.read()
This implementation processed the file in under 1 minute!