from collections import Counter, defaultdict
from itertools import imap
import re
codes = ['200', '3xx', '4xx', '5xx']
regex = re.compile('^.+?\[(?P<date>.+?) .+?\].+?(?P<code>\d+) \d+ ".+?" ".+?"$')
stats = defaultdict(Counter)
with open('access.log', 'r') as f:
for date, code in (match.groups() for match in imap(regex.match, f) if match):
stats[date].update([code if code == '200' else '{}xx'.format(code[0])])
for date, items in sorted(stats.iteritems()):
print date, ' '.join(str(items[code]) for code in codes)
# ---------- И ещё вариант ----------
from collections import Counter, defaultdict
from itertools import imap
from operator import methodcaller as mc
import re
codes = ['200', '3xx', '4xx', '5xx']
regex = re.compile('^.+?\[(?P<date>.+?) .+?\].+?(?P<code>\d+) \d+ ".+?" ".+?"$')
stats = defaultdict(Counter)
def fmt(code):
return code if code == '200' else '%sxx' % code[0],
with open('access.log', 'r') as f:
reduce(
lambda _, (date, code): stats[date].update(fmt(code)),
imap(mc('groups'), imap(regex.match, f)), None
)
for date, items in sorted(stats.iteritems()):
print date, ' '.join(imap(str, imap(items.__getitem__, codes)))
</code>