0

我正在尝试遍历多个日志文件,并且需要对正在循环的所有文件中的文件条目(行)进行排序

这就是我正在做的事情:

import glob

f = glob.glob('logs/')
for line in sorted(fileinput.input(f), key=stringsplit(line)):
  print line

所以,我正在打开所有文件,然后想使用 stringssplit 函数(从文件条目中提取日期)作为排序标准。

问题是,这样做会给我一个错误说:

name 'line' is not defined

问题:
不能将line被循环作为参数传递给排序函数吗?如何才能做到这一点?

谢谢!

4

2 回答 2

2

试试key=lambda line: stringsplit(line)

排序是在您开始迭代 for 循环之前完成的。

于 2013-03-08T15:43:54.617 回答
1

key关键字必须是可调用的。输入序列中的每个条目都会调用它。

Alambda是创建这样一个可调用对象的简单方法:

sorted(..., key=lambda line: stringsplit(line))

不过,我会非常谨慎地对fileinput许多大文件的输出进行排序。sorted() 必须将所有行读入内存才能对它们进行排序。如果您的文件很多和/或很大,您将用完所有内存,最终导致MemoryError异常。

首先使用不同的方法对日志进行预排序。您可以使用 UNIX 工具sort,或者使用外部排序技术

如果您的输入文件已经排序,您可以使用相同的键合并它们:

import operator

def mergeiter(*iterables, **kwargs):
    """Given a set of sorted iterables, yield the next value in merged order"""
    iterables = [iter(it) for it in iterables]
    iterables = {i: [next(it), i, it] for i, it in enumerate(iterables)}
    if 'key' not in kwargs:
        key = operator.itemgetter(0)
    else:
        key = lambda item, key=kwargs['key']: key(item[0])

    while True:
        value, i, it = min(iterables.values(), key=key)
        yield value
        try:
            iterables[i][0] = next(it)
        except StopIteration:
            del iterables[i]
            if not iterables:
                raise

然后传入你打开的文件对象:

files = [open(f) for f in glob.glob('logs/*')]
for line in mergeiter(*files, key=lambda line: stringsplit(line)):
    # lines are looped over in merged order.

但是您需要确保函数返回的stringsplit()值按照输入日志文件中的顺序返回。

于 2013-03-08T15:43:07.470 回答