为了账号安全,请及时绑定邮箱和手机立即绑定

你如何优化在 Python 中搜索大文件

你如何优化在 Python 中搜索大文件

一只甜甜圈 2023-06-20 14:32:55
我有一个包含大约 800 万行文件名的大文件,我正在尝试搜索包含特定值的文件名。找到一个很好,但问题是我正在尝试搜索大约 50k 个唯一值,而且搜索所需的时间非常长。with open('UniqueValueList.txt') as g:    uniqueValues = g.read().splitlines()outF = open("Filenames_With_Unique_Values.txt", "w")with open('Filenames_File.txt') as f:    fileLine = f.readlines()    for line in fileLine:        for value in uniqueValues:            if value in line:                outF.write(line)outF.close()我无法将 filenames 文件加载到内存中,因为它太大了。还有其他方法可以优化此搜索吗?
查看完整描述

2 回答

?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

我的两个理论是 (1) 内存映射文件并为每个值搜索使用多行正则表达式,以及 (2) 将工作分配给多个子进程。我将两者结合起来,得出以下结论。也许可以在父进程中执行 mmap 并共享,但我走的是简单的路线,只是在每个子进程中都这样做,假设操作系统会为您找出有效的共享。


import multiprocessing as mp

import os

import mmap

import re


def _value_find_worker_init(filename):

    """Called when initializing mp.Pool to open an mmaped file in subprocesses.

    The file is `global mmap_file` so that the worker can find it.

    """

    global mmap_file

    filenames_fd = os.open(filename, os.O_RDONLY)

    mmap_file = mmap.mmap(filenames_fd, length=os.stat(filename).st_size,

        access=mmap.ACCESS_READ)


def _value_find_worker(value):

    """Return a list of matching lines in `global mmap_file`"""

    # multiline regex for findall

    regex = b"(?m)^.*?" + value + b".*?$"

    matched = re.compile(regex).findall(mmap_file)

    print(regex, matched)

    return matched


def find_unique():

    with open("UniqueValueList.txt", "rb") as g:

        uniqueValues = [line.strip() for line in g]

    with open('UniqueValueList.txt', "rb") as g:

        uniqueValues = [line.strip() for line in g]

    with mp.Pool(initializer=_value_find_worker_init,

            initargs=("Filenames_File.txt",)) as pool:

        matched_values = set()

        for matches in pool.imap_unordered(_value_find_worker, uniqueValues):

            matched_values.update(matches)

    with open("Filenames_With_Unique_Values.txt", "wb") as outfile:

        outfile.writelines(value + b"\n" for value in matched_values)


find_unique()


查看完整回答
反对 回复 2023-06-20
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

我们可以将文件对象用作迭代器。迭代器会逐行返回每一行,可以处理。这不会将整个文件读入内存,适合在 Python 中读取大文件。

查看完整回答
反对 回复 2023-06-20
  • 2 回答
  • 0 关注
  • 105 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信