在Python中查找文件中间位置

3
我正在编写一个程序,用于在一个非常大(无序)的文件中搜索特定行(因此最好不要将整个文件加载到内存中)。 我正在实现多线程以加快进程速度。 我正在尝试为特定线程提供文件的特定部分,即第一个线程将通过文件的前四分之一运行,第二个线程同时扫描从第一个线程停止的终点开始等等。
因此,为了做到这一点,我需要找到文件不同部分的字节位置,为了简化问题,假设我只想找到文件的中间部分。 但问题是每行的长度都不同,所以如果我只是这样做
fo.seek(0, 2)
end = fo.tell()
mid = end/2
fo.seek(mid, 0)

它可以给我一行的中间位置。因此,我需要一种方法来查找下一个或上一个换行符。此外,请注意,我不想要确切的中间位置,只需要大致靠近它(因为它是一个非常大的文件)。
以下是我能够编写的代码。我不确定它是否将文件加载到内存中。而且,我真的想避免打开两个相同文件的实例(在我的程序中,我这样做是因为我不想担心读取文件时偏移量会改变)。
如果有任何修改(或新程序),可以更快地运行,那将不胜感激。
fo = open(filename, "rw+")
f2 = open(filename, "rw+")

file_ = dict()

fo.seek(0, 2)
file_['end'] = fo.tell()

file_['mid'] = file_['end'] / 2

fo.seek(file_['mid'], 0)
f2.seek(file_['mid'], 0)

line =  f2.readline()

fo.seek(f2.tell(), 0)
file_['mid'] = f2.tell()


fo.seek(file_['mid'], 0)

print fo.readline()

2
一如既往,IO 操作很少从多线程中获得速度提升。我无法解读你的代码,但我猜在 fo.seek(file_['mid']); fo.readline() 之后你已经到了一个新行,也就是说你要找的不是 fo.tell() 吗? - alko
@alko 我认为在Python中,多线程的唯一目的是帮助处理IO操作,而多进程则是帮助处理CPU操作... - Steve P.
2
请阅读以下链接内容:https://dev59.com/LnA75IYBdhLWcg3w4tR7#3055497 - alko
@alko 好的,但如果我必须将这行代码发送到另一个系统以进行检查,例如使用urllib发送请求。那么多线程会有帮助吗? - Grim Reaper
3
如果你的读取速度受限,"两个线程从两个不同的方向搜索一行"将会以每个线程的速度为“一个线性搜索单线程的一半”的速度运行。如果你的检查很昂贵(例如,你正在查询外部服务),那么在一个线程中线性读取文件并使用工作池并行进行检查更简单和易于阅读。 - Lie Ryan
显示剩余7条评论
1个回答

3

“非常大”有多大呢?即使是1-10GB的文件,grep也能迅速地搜索。

如果这个文件是静态的,并且您计划重复搜索它,您可以使用split命令将其分割成多个部分:

split -l <line_count> <file>

现在你有多个文件,可以将每个文件传递给单独的线程/进程/其他操作。
文件是否已排序?这会改变情况,因为现在您可以使用fo.seek()调用进行二进制搜索。
速度有多快才够快?超过一定点后,您将不得不构建搜索索引。在那之前,像grepsplit等简单工具都能发挥奇效。
没有更多信息,无法确定权衡利弊的正确方法。

文件大小可能在2-8 GB之间。不,该文件未排序。拆分似乎是一个不错的选择。 - Grim Reaper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接