python - 在 python 中从文件中获取多个值的最快方法

标签 python grep

  • 我有一个 300m 行的文件 (inputFile),所有文件都有 2 列,用制表符分隔。
  • 我还有一个包含 1000 个唯一项 (vals) 的列表。

我想为 inputFile 中的所有行创建一个字典,其中第 1 列作为键,第 2 列作为值,其中第一列出现在 vals 中。 vals 中的一些项目没有出现在文件中,这些值必须保存在新列表中。我最多可以使用 20 个线程来加速这个过程。

实现此目标的最快方法是什么?

到目前为止我的最佳尝试:

newDict = {}
foundVals = []
cmd = "grep \"" + vals[0]
for val in vals:
     cmd = cmd + "\|^"+val+"[[:space:]]"
cmd = cmd + "\" " + self.inputFile
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, ''):
    info = line.split()
    foundVals.append(info[0])
    newDict.update({info[0]:info[1]})
p.wait()
notFound = [x for x in vals if x not in set(foundVals)]

例子 输入文件:

2       9913
3       9913
4       9646
...
594592886       32630
594592888       32630
594592890       32630

值:

[1,2,594592888]

想要的字典:

{2:9913,594592888:32630}

在 notFound 中:

[1]

最佳答案

您在评论中阐明每个键在数据中最多出现一次。从这一点以及只有 1000 个键的事实可以看出,在 Python 中完成的工作量是微不足道的;您几乎所有的时间都花在了等待 grep 的输出上。哪个好;您将线路提取委托(delegate)给专门的实用程序的策略仍然有效。但这意味着必须在行提取方面找到性能提升。

您可以通过优化您的正则表达式来加快速度。例如,而不是

^266[[:space:]]\|^801[[:space:]]\|^810[[:space:]]

你可以使用:

^\(266\|801\|810\)[[:space:]]

这样就不必为每个备选方案单独匹配 anchor 。我发现通过该更改,测试数据(1000 万行,25 个键)提高了大约 15%。

进一步的优化是统一交替中的公共(public)前缀:266\|801\|810 可以替换为等效的 266\|8\(01\|10\) 。以这种方式重写 25 键正则表达式可使测试数据加速接近 50%。

此时 grep 开始显示其局限性。它似乎受 CPU 限制:iostat 表明,在 grep 运行时,正则表达式的每一次连续改进都会增加每秒 IO 请求的数量。并且使用预热页面缓存和 --mmap 选项重新运行 grep 不会加快速度(如果文件 IO 是瓶颈,它可能会加快速度)。因此,更快的速度可能需要具有更快的正则表达式引擎的实用程序。

其中一个是 ag(来源 here ),其正则表达式实现也执行自动优化,因此您无需进行太多手动调整。虽然我无法让 grep 在我的机器上在不到 ~12 秒的时间内处理测试数据,但 ag 对所有正则表达式变体在 ~0.5 秒内完成如上所述。

关于python - 在 python 中从文件中获取多个值的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22480514/

相关文章:

python - 无法为 Pandas 中的某些列赋值

linux - BASH 在变量中使用 grep 和 awk

regex - grep 文件名[星号] 返回意外结果

python - FastAPI 和 Python 线程

python - 在python中按不同键对字典列表进行排序

python - Django 查询集 : filter by 'value LIKE column'

正则表达式:查找不以特定前缀开头的字符串

regex - 在 URL 列表中查找域部分中的关键字

linux - 数 = 'ps -ef | grep -v grep| grep BatchName| wc -l'

python - now() 在 DateTime 2.12 中移动到哪里