【问题标题】:How to enhance the performance of finding the most common strings in Python?如何提高在 Python 中查找最常见字符串的性能?
【发布时间】:2013-09-08 15:01:18
【问题描述】:

我有大约 30 个文件,每个文件的大小约为 300MB。每个文件中都有一些我感兴趣的信息,例如用户名。现在我想使用正则表达式查找用户名,然后找到最常见的用户名。这是我的代码:

rList=[]
for files in os.listdir("."):
    with open(files,'r') as f:
        for line in f:
            m=re.search('PATTERN TO FIND USERNAME',line)
            if m:
                rList.append(m.group())             
c=Counter(rList)
print c.most_common(10)

现在如您所见,我将找到的每个用户名都添加到列表中,然后调用 Counter()。这样大约需要几分钟才能完成。我尝试删除c=Counter(rList) 并在每次读完文件时调用c.update(),但这不会有任何区别,不是吗?

那么,这是最佳做法吗?有什么方法可以提高性能吗?谢谢!

【问题讨论】:

  • 瓶颈可能是从磁盘读取 9 GB。不过,您绝对应该预编译正则表达式。
  • 尝试通过分析器运行它,它会让您了解需要优化的部分。
  • 您似乎在代码中有错误,我认为with open... 行和接下来的4行应该缩进。您可以使用timeit 模块来找出代码中的瓶颈所在。 @Ben 实际上,python 将缓存 regex 的最新值,因此此 sn-p 不需要预编译,请参阅 the docs。但是,如果整个程序中还有其他正则表达式,编译可能会有所帮助。
  • 呵呵,你每天都能学到新东西。好提示!
  • 使用mmap 从文件中读取行。 Example 在 SO。

标签: python performance algorithm sorting counter


【解决方案1】:

分析将告诉您,在文件的每一行上逐行循环会产生大量开销。如果文件总是在您指定的大小附近并且您可以使用内存,则通过一次调用 .read() 将它们放入内存,然后使用更复杂的预编译正则表达式(考虑换行符)来一次提取所有用户名。然后.update() 您的反对象与匹配的正则表达式中的组。这将尽可能高效。

【讨论】:

    【解决方案2】:

    如果你有记忆,那么:

    1. 使用映射
    2. 尽可能使用隐式循环

    以下片段应该很快但需要内存:

    # imports elided
    
    patternString = rb'\b[a-zA-Z]+\b' # byte string creating a byte pattern
    pattern = re.compile(patternString)
    c = Counter()
    
    for fname in os.listdir("."):
        with open(fname, "r+b") as f:
            mm = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
            c.update(pattern.findall(mm))
    print(c.most_common(10))
    

    patternString 应该是你的模式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-24
      • 2017-03-30
      • 2018-05-23
      • 2020-02-23
      • 1970-01-01
      • 2012-12-08
      • 2014-12-14
      • 2011-02-03
      相关资源
      最近更新 更多