Сценарий Python, который выполняет сопоставление строк над устаревшими файлами, генерирует противоречивый вывод
Я создал скрипт Python для анализа почтовых (exim) файлов журналов и выполнения сопоставления с образцом, чтобы получить список топ-100 для большинства отправляемых доменов на моих серверах smtp. Однако каждый раз, когда я выполняю сценарий, я получаю различное количество. Это устаревшие лог-файлы, и я не могу найти функциональный недостаток в моем коде.
Example output:
1:
70353 gmail.com
68337 hotmail.com
53657 yahoo.com
2:
70020 gmail.com
67741 hotmail.com
54397 yahoo.com
3:
70191 gmail.com
67917 hotmail.com
54438 yahoo.com
Code:
#!/usr/bin/env python
import os
import datetime
import re
from collections import defaultdict
class DomainCounter(object):
def __init__(self):
self.base_path = '/opt/mail_log'
self.tmp = []
self.date = datetime.date.today() - datetime.timedelta(days=14)
self.file_out = '/var/tmp/parsed_exim_files-' + str(self.date.strftime('%Y%m%d')) + '.decompressed'
def parse_log_files(self):
sub_dir = os.listdir(self.base_path)
for directory in sub_dir:
if re.search('smtp\d+', directory):
fileInput = self.base_path + '/' + directory + '/maillog-' + str(self.date.strftime('%Y%m%d')) + '.bz2'
if not os.path.isfile(self.file_out):
os.popen('touch ' + self.file_out)
proccessFiles = os.popen('/bin/bunzip2 -cd ' + fileInput + ' > ' + self.file_out)
accessFileHandle = open(self.file_out, 'r')
readFileHandle = accessFileHandle.readlines()
print "Proccessing %s." % fileInput
for line in readFileHandle:
if '<=' in line and ' for ' in line and '<>' not in line:
distinctLine = line.split(' for ')
recipientAddresses = distinctLine[1].strip()
recipientAddressList = recipientAddresses.strip().split(' ')
if len(recipientAddressList) > 1:
for emailaddress in recipientAddressList:
# Since syslog messages are transmitted over UDP some messages are dropped and needs to be filtered out.
if '@' in emailaddress:
(login, domein) = emailaddress.split("@")
self.tmp.append(domein)
continue
else:
try:
(login, domein) = recipientAddressList[0].split("@")
self.tmp.append(domein)
except Exception as e:
print e, '<<No valid email address found, skipping line>>'
accessFileHandle.close()
os.unlink(self.file_out)
return self.tmp
if __name__ == '__main__':
domainCounter = DomainCounter()
result = domainCounter.parse_log_files()
domainCounts = defaultdict(int)
top = 100
for domain in result:
domainCounts[domain] += 1
sortedDict = dict(sorted(domainCounts.items(), key=lambda x: x[1], reverse=True)[:int(top)])
for w in sorted(sortedDict, key=sortedDict.get, reverse=True):
print '%-3s %s' % (sortedDict[w], w)
1 ответ
proccessFiles = os.popen('/bin/bunzip2 -cd ' + fileInput + ' > ' + self.file_out)
Эта строка неблокирующая. Поэтому он запустит команду, но несколько следующих строк уже читают файл. Это в основном проблема параллелизма. Попробуйте дождаться завершения команды, прежде чем читать файл.
Также смотрите: Команда Python popen. Подождите, пока команда не закончится с os.popen
устарела начиная с python-2.6 (в зависимости от того, какую версию вы используете).
Sidenote - То же самое происходит со строкой ниже. Файл может существовать или не существовать после выполнения следующей строки:
os.popen('touch ' + self.file_out)