Дано: сотни логов веб-сервера, разбросанные по разным директориям. Возможно, заархивированные.
Требуется: понять сколько байтов было передано :)
В питоне есть замечательная функция os.walk(), позволяющая блуждать по файловой системе:
Для достижения цели потребуется создать несколько функций:
1. Функция-генератор, возвращающая список файлов по заданному шаблону:
Примеры использования:
2. Функция-генератор, которая принимает список файлов, и, если среди них есть архивы, то возвращает распакованные файлы. Если файл не архив, то просто открывает его:
3. Функция (разумеется генератор), которая возвращает единую последовательность результатов, принимая при этом несколько последовательностей (в нашем случае передаем открытые файлы, а получаем последовательность строк):
def gen_cat(sources):
for s in sources:
for item in s:
yield item
Ну вот, после реализации всех этих функций осталось только немного подправить прошлый исходник, чтобы он теперь работал с любым количеством файлов:
Особые эстеты могут свернуть этот исходник вплоть до 1 строчки, благодаря тому факту, что в питоне все функции - высшего порядка.
Требуется: понять сколько байтов было передано :)
В питоне есть замечательная функция os.walk(), позволяющая блуждать по файловой системе:
import os
for path, dirlist, filelist in os.walk(topdir):
# path : текущая директория
# dirlist : список поддиректорий
# filelist : список файлов
...
Для достижения цели потребуется создать несколько функций:
1. Функция-генератор, возвращающая список файлов по заданному шаблону:
import os
import fnmatch
import fnmatch
def gen_find(filepat,top):
for path, dirlist, filelist in os.walk(top):
for name in fnmatch.filter(filelist, filepat):
yield os.path.join(path, name)
for path, dirlist, filelist in os.walk(top):
for name in fnmatch.filter(filelist, filepat):
yield os.path.join(path, name)
Примеры использования:
pyfiles = gen_find('*.py', '/')
logs = gen_find('access-log*', '/usr/www/')
logs = gen_find('access-log*', '/usr/www/')
2. Функция-генератор, которая принимает список файлов, и, если среди них есть архивы, то возвращает распакованные файлы. Если файл не архив, то просто открывает его:
import gzip
import bz2
def gen_open(filenames):
for name in filenames:
if name.endswith(".gz"):
yield gzip.open(name)
elif name.endswith(".bz2"):
yield bz2.BZ2File(name)
else:
yield open(name)
for name in filenames:
if name.endswith(".gz"):
yield gzip.open(name)
elif name.endswith(".bz2"):
yield bz2.BZ2File(name)
else:
yield open(name)
3. Функция (разумеется генератор), которая возвращает единую последовательность результатов, принимая при этом несколько последовательностей (в нашем случае передаем открытые файлы, а получаем последовательность строк):
def gen_cat(sources):
for s in sources:
for item in s:
yield item
Ну вот, после реализации всех этих функций осталось только немного подправить прошлый исходник, чтобы он теперь работал с любым количеством файлов:
filenames = gen_find('access-log*', '/usr/www')
logfiles = gen_open(filenames)
loglines = gen_cat(logfiles)
bytecolumn = (line.rsplit(None, 1)[1] for line in loglines)
bytes = (int(x) for x in bytecolumn if x != '-')
print "Total", sum(bytes)
logfiles = gen_open(filenames)
loglines = gen_cat(logfiles)
bytecolumn = (line.rsplit(None, 1)[1] for line in loglines)
bytes = (int(x) for x in bytecolumn if x != '-')
print "Total", sum(bytes)
Особые эстеты могут свернуть этот исходник вплоть до 1 строчки, благодаря тому факту, что в питоне все функции - высшего порядка.
No comments:
Post a Comment