Python中遍历大文件(10GB+)的最有效方法

2024-09-25 06:34:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个Python脚本来遍历两个文件—一个包含uuid列表,另一个包含大量日志条目—每一行包含另一个文件中的一个uuid。程序的目的是从文件1创建一个UUID列表,然后每次在日志文件中找到该UUID时,为每次找到匹配项增加关联的值。

长话短说,计算每个UUID在日志文件中出现的次数。 目前,我有一个列表,其中以UUID作为键,以hits作为值。然后是另一个循环,循环遍历日志文件的每一行,并检查日志中的UUID是否与UUID列表中的UUID匹配。如果匹配,则会增加值。

    for i, logLine in enumerate(logHandle):         #start matching UUID entries in log file to UUID from rulebase
        if logFunc.progress(lineCount, logSize):    #check progress
            print logFunc.progress(lineCount, logSize)  #print progress in 10% intervals
        for uid in uidHits:
            if logLine.count(uid) == 1:             #for each UUID, check the current line of the log for a match in the UUID list
                uidHits[uid] += 1                   #if matched, increment the relevant value in the uidHits list
                break                                #as we've already found the match, don't process the rest
        lineCount += 1               

它可以正常工作,但我相信有一种更有效的方法来处理文件。我看过一些指南,发现使用“count”比使用编译的regex快。我认为将文件分块读取而不是逐行读取可以通过减少磁盘I/O时间来提高性能,但测试文件~200MB的性能差异是可以忽略的。如果有人有其他方法,我将非常感激:)


Tags: 文件theinlog列表foruidif
3条回答

从功能上考虑!

  1. 编写一个函数,它将获取日志文件的一行并返回uuid。比如说,叫它uuid

  2. 将此函数应用于日志文件的每一行。如果使用的是Python3,则可以使用内置函数映射;否则,需要使用itertools.imap。

  3. 将此迭代器传递给collections.Counter。

    collections.Counter(map(uuid, open("log.txt")))
    

这将是非常有效的。

一些评论:

  • 这完全忽略了uuid的列表,只统计出现在日志文件中的uuid。如果您不想这样做,您需要对程序进行一些修改。

    • 您的代码很慢,因为您使用了错误的数据结构。你在这里想要的就是口述。

就像上面提到的,使用一个10GB的文件,你可能会很快达到磁盘的极限。对于纯代码的改进,生成器的建议非常好。在Python2.x中,它看起来像

uuid_generator = (line.split(SPLIT_CHAR)[UUID_FIELD] for line in file)

听起来这不一定是python的问题。如果您没有做任何比计算uuid更复杂的事情,那么Unix可能比python更快地解决您的问题。

cut -d${SPLIT_CHAR} -f${UUID_FIELD} log_file.txt | sort | uniq -c 

这不是你问题的5行答案,但是在PyCon'08上有一个很好的教程叫做Generator Tricks for System Programmers。还有一个叫做A Curious Course on Coroutines and Concurrency的后续教程。

生成器教程特别使用大日志文件处理作为其示例。

相关问题 更多 >