Python 在大文件中高效地搜索许多不同的字符串

Python 在大文件中高效地搜索许多不同的字符串,python,performance,string-search,Python,Performance,String Search,我试图找到一种快速搜索文件中字符串的方法。首先,我不是只有一个字符串可以找到。我在一个150MB的文件中找到了1900个字符串的列表。基本上,我打开一个文件,循环1900次,以找到该文件中出现的所有字符串。以下是我搜索的一些属性 要搜索的文件大小为150mb–它是文本文件 我需要在一个文件中找到所有出现的1900个字符串。意味着我将整个文件循环1900次以搜索所有事件 这不是简单的搜索,我必须使用正则表达式来搜索字符串 在少数情况下,我需要在找到搜索字符串的位置上方和下方各有一行。所以我需要使用

我试图找到一种快速搜索文件中字符串的方法。首先,我不是只有一个字符串可以找到。我在一个150MB的文件中找到了1900个字符串的列表。基本上,我打开一个文件,循环1900次,以找到该文件中出现的所有字符串。以下是我搜索的一些属性

  • 要搜索的文件大小为150mb–它是文本文件
  • 我需要在一个文件中找到所有出现的1900个字符串。意味着我将整个文件循环1900次以搜索所有事件
  • 这不是简单的搜索,我必须使用正则表达式来搜索字符串
  • 在少数情况下,我需要在找到搜索字符串的位置上方和下方各有一行。所以我需要使用file.readlines()而不是file.read()
  • 在少数情况下,我还必须用新字符串替换搜索的字符串
  • 首先,我试图找到在文件中搜索的最佳方式。我的代码太长了。我不确定这是否是最好的方法:

    #searchstrings is list of 1900 strings
    file = open("mytextfile.txt", "r")
    for line in file:
        for i in range(len(searchstrings)):
            if searchstrings[i] in line:
                print(line)
    file.close()
    
    这段代码可以完成这项工作,但速度非常慢。此外,它也没有给我选择搜索字符串所在位置上方或下方的行的选项

    我用来替换字符串的另一个代码如下所示。这段代码也非常慢。这里我使用正则表达式

    file = open("mytextfile.txt", "r")
    file_data = file.read()
    #searchstrings is list of 1900 strings
    #replacestrings is list of 1900 strings that needs to be replaced
    for i in range(len(searchstrings)):
        src_str = re.compile(searchstrings[i], re.IGNORECASE)
        file_data = src_str.sub(replacestrings[i], file_data)
    file.close()
    
    我知道代码的性能也取决于计算能力,但是,我只想知道,对于给定的硬件,以最佳速度编写代码的最佳方法是什么。我还想知道如何给程序执行计时。

    一些观察结果

    对于惯用Python,您通常需要

    for string in searchstrings:
        ...
    
    而不是

    for i in range(len(searchstrings)):
        searchstrings[i]
    
    并且
    将open(filename)作为f:…
    而不是
    open()/close()
    with
    语句将自动关闭文件

    当您想用正则表达式替换多个字符串中的任何一个时,您可以这样做

    re.sub('|'.join(YOUR_STRINGS), replacement, text)
    
    因为
    |
    是“or”的正则表达式符号,而不是单独循环

    为了提高性能,我可能会尝试从CPython切换到。PyPy是同一语言的另一种实现,但通常要快得多

    另一方面,如果这就是你的程序应该做的所有事情,你可能想使用一个专门的工具来完成这项工作,比如Ag或RipGrep,它已经为此项工作进行了优化。如果您使用的是Python,则可能通过
    subprocess.run()
    函数执行。

    一些观察结果

    对于惯用Python,您通常需要

    for string in searchstrings:
        ...
    
    而不是

    for i in range(len(searchstrings)):
        searchstrings[i]
    
    并且
    将open(filename)作为f:…
    而不是
    open()/close()
    with
    语句将自动关闭文件

    当您想用正则表达式替换多个字符串中的任何一个时,您可以这样做

    re.sub('|'.join(YOUR_STRINGS), replacement, text)
    
    因为
    |
    是“or”的正则表达式符号,而不是单独循环

    为了提高性能,我可能会尝试从CPython切换到。PyPy是同一语言的另一种实现,但通常要快得多


    另一方面,如果这就是你的程序应该做的所有事情,你可能想使用一个专门的工具来完成这项工作,比如Ag或RipGrep,它已经为此项工作进行了优化。如果您使用的是Python,则可能通过
    subprocess.run()
    函数执行。

    我喜欢Unix命令,它们有趣、快速且高效

    import re, sys
    map(sys.stdout.write,(string_x for string_x in sys.stdin if re.search(sys.argv[1],string_x)))
    

    我喜欢Unix命令,它们有趣、快速、高效

    import re, sys
    map(sys.stdout.write,(string_x for string_x in sys.stdin if re.search(sys.argv[1],string_x)))
    

    为了获得最佳性能,
    search\u re=re.compile(“|”).join(strings),…)
    应该在循环行之前执行一次。然后每行可以调用一次
    search\u re.sub
    。@SethMMorton当然可以,但在实践中,模式是否手动编译(一次或多次)可能没有多大关系,因为它无论如何都在
    re
    模块中。我听到人们这么说,但实际上我已经对它进行了计时,并发现这很重要。但即使不是这样,多次执行
    “|”.join
    的成本也很重要。所以当你说re.sub(“|”).join(你的_字符串)、replacement、text)时,我必须为1900个字符串这么做?我必须连接1900个字符串?为了获得最佳性能,
    search\u re=re.compile(“|”).join(strings),…)
    应该在循环行之前执行一次。然后每行可以调用一次
    search\u re.sub
    。@SethMMorton当然可以,但在实践中,模式是否手动编译(一次或多次)可能没有多大关系,因为它无论如何都在
    re
    模块中。我听到人们这么说,但实际上我已经对它进行了计时,并发现这很重要。但即使不是这样,多次执行
    “|”.join
    的成本也很重要。所以当你说re.sub(“|”).join(你的_字符串)、replacement、text)时,我必须为1900个字符串这么做?我必须连接1900个字符串?您可以指定预期的输出格式。例如,您希望所有结果都在一个列表中,还是希望分别存储每个搜索字符串的结果?此外,您是否只需要存储某些搜索的结果,而对于其他搜索,您只需执行操作?关于计时,请参阅。您可以指定预期的输出格式。例如,您希望所有结果都在一个列表中,还是希望分别存储每个搜索字符串的结果?此外,您是否只需要存储某些搜索的结果,而对于其他搜索,您只需执行操作?关于计时,请参阅。