【问题标题】:Optimize regex and file reading operation on big files in python优化python中大文件的正则表达式和文件读取操作
【发布时间】:2015-02-06 14:26:04
【问题描述】:

现在我有两个大文件,pattern filelog file,每个都有超过300,000行。模式文件的格式如下:

Line 1 : <ID>   <Dialog1>    <ReplyStr>    <Dialog2>    
// the ReplyStr is needed as a pattern

日志文件的格式如下:

Line 1 : <LogData>    <ReplyStr>    <CommentOfReply>   
// get all CommentOfReply, whose ReplyStr is from the pattern file

我的任务是从特定回复中获取所有评论,以分析用户对这些给定回复的情绪。所以这是我一步一步做的:

  1. 挑选所有模式和日志,它们都使用正则表达式,
  2. 然后将它们与字符串比较操作一起匹配。

我需要优化代码,目前需要 8 个小时才能完成。

配置文件如下(在前 10 个循环中使用 cProfile):

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   19.345   19.345 <string>:1(<module>)
        1    7.275    7.275   19.345   19.345 get_candidate2.py:12(foo)
  3331494    2.239    0.000   10.772    0.000 re.py:139(search)
  3331496    4.314    0.000    5.293    0.000 re.py:226(_compile)
      7/2    0.000    0.000    0.000    0.000 sre_compile.py:32(_compile)
                            ......
  3331507    0.632    0.000    0.632    0.000 {method 'get' of 'dict' objects}
  3331260    0.560    0.000    0.560    0.000 {method 'group' of '_sre.SRE_Match' objects}
        2    0.000    0.000    0.000    0.000 {method 'items' of 'dict' objects}
        2    0.000    0.000    0.000    0.000 {method 'remove' of 'list' objects}
  3331494    3.241    0.000    3.241    0.000 {method 'search' of '_sre.SRE_Pattern' objects}
        9    0.000    0.000    0.000    0.000 {method 'split' of 'str' objects}
  6662529    0.737    0.000    0.737    0.000 {method 'strip' of 'str' objects}

从配置文件来看,似乎所有耗时都来自re.search()。我不知道如何减少它。

【问题讨论】:

  • 所以您正试图对 300,000 行执行 300,000 次单独搜索?这听起来像是 10^11 左右的操作,这确实需要很长时间。也许你需要重新考虑你想要达到的目标。但如果你把它充实一点,它可能会成为一个有趣的问题。您能否与我们分享更多有关要搜索的特定模式和文本的信息?为什么需要这么多模式?这个项目的总体目标是什么?
  • 你不能只迭代一次日志文件并创建一个大字典{replyStr: [CommentOfReply, ...]}吗?然后迭代模式文件并一次获取所有回复的 cmets。
  • @stanleyerror 如果您提供两个文件的一小段代表性摘录(可能大约十行),那么如果需要,我可能会编写一些示例代码来帮助您入门。
  • @tobias_k 哈哈,你真好。好吧,我应该独立解决,因为这是我的任务。无论如何,您的解决方案很有帮助。
  • 你自己完成的愿望令人钦佩。不要忘记,一旦您开发了解决方案,您可以根据需要回答自己的问题。

标签: python regex optimization profile


【解决方案1】:

感谢@MikeSatteson 和@tobias_k 的帮助,我弄明白了。

要从给定的回复字符串(来自pattern file)中挑选出所有的评论字符串(来自日志文件),解决方法是:

  1. 需要一个dict,key是回复字符串,value是评论字符串列表。
  2. pattern file中挑选出所有回复字符串,作为dict的key set。
  3. 日志文件中挑选出所有的reply-comment对,如果dict的key set包含reply,则将comment附加到comment list中。

代码如下:

my_dict = {}
with open('pattern file', 'r') as pattern_file:
    for line in pattern_file:
        reply = get_reply(line)
        my_dict[reply] = list()     

with open('log file', 'r') as log_file:
    for line in log_file:
        pair = get_comment_reply_pair(line)
        reply = pair.reply
        comment  = pair.comment
        if reply in my_dict:
            l = my_dict[reply]
            l.append(comment)

【讨论】:

  • 很高兴看到你想通了!两个小建议:您可以使用with open('pattern file') as pattern_file: 自动关闭文件,您可以使用if reply in my_dict
  • 干得好@stanleyerror!我很高兴您发现我的 cmets 很有帮助。
  • @tobias_k 我已经根据您的建议改进了答案。 with open() as 是缓冲阅读器吗,我的意思是在需要时将行加载到内存中?
  • @stanleyerror 这与您是否使用with 无关。如果你使用for line in pattern_file,文件是逐行读取的,而如果你使用lines = pattern_file.readlines(),你会一次读取整个文件。 with 所做的只是确保文件已关闭,即使发生某种错误也是如此。有关with 的更多信息,请参阅here
猜你喜欢
  • 2015-11-23
  • 1970-01-01
  • 2013-04-08
  • 2016-07-25
  • 1970-01-01
  • 2017-06-12
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多