Python中最有效的迭代大文件的方式(10GB +)

SG8*_*G84 12 python design-patterns file matching

我正在编写一个Python脚本来浏览两个文件 - 一个包含UUID列表,另一个包含大量日志条目 - 每行包含一个来自另一个文件的UUID.该程序的目的是从file1创建UUIDS列表,然后每次在日志文件中找到UUID时,每次找到匹配时增加相关值.

长话短说,计算每个UUID出现在日志文件中的次数.目前,我有一个列表,其中填充了UUID作为键,并且"点击"作为值.然后是另一个循环,它迭代日志文件的每一行,并检查日志中的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               
Run Code Online (Sandbox Code Playgroud)

它可以正常工作 - 但我确信有一种更有效的方法来处理文件.我经历了一些指南,发现使用'count'比使用编译的正则表达式更快.我认为以块为单位而不是逐行读取文件可以通过减少磁盘I/O时间来提高性能,但测试文件~200MB的性能差异可以忽略不计.如果有人有任何其他方法我会非常感激:)

Kat*_*iel 14

从功能上思考!

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

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

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

    collections.Counter(map(uuid, open("log.txt")))
    
    Run Code Online (Sandbox Code Playgroud)

这将是非常有效的.

一对评论:

  • 这完全忽略了UUID列表,只计算出现在日志文件中的UUID.如果你不想要这个,你需要稍微修改一下程序.

    • 您的代码很慢,因为您使用了错误的数据结构.dict是你想要的.

  • @ SG84你可能会看到关于Python的生成器http://www.dabeaz.com/generators/Generators.pdf的优秀文章,特别是对于处理大文件.你会开心的:-) (5认同)