我需要使用 python 从大 txt 文件中获取 N 行。这些文件基本上是制表符分隔的表。我的任务有以下限制:
- 这些文件可能包含标题(有些具有多行标题)。
- 标题需要以相同的顺序出现在输出中。
- 每条线只能取一次。
- 目前最大的文件约为 150GB(约 60 000 000 行)。
- 文件中的行长度大致相同,但在不同文件之间可能会有所不同。
- 我通常会随机抽取 5000 行(我可能需要多达 1 000 000 行)
目前我已经编写了以下代码:
inputSize=os.path.getsize(options.input)
usedPositions=[] #Start positions of the lines already in output
with open(options.input) as input:
with open(options.output, 'w') as output:
#Handling of header lines
for i in range(int(options.header)):
output.write(input.readline())
usedPositions.append(input.tell())
# Find and write all random lines, except last
for j in range(int(args[0])):
input.seek(random.randrange(inputSize)) # Seek to random position in file (probably middle of line)
input.readline() # Read the line (probably incomplete). Next input.readline() results in a complete line.
while input.tell() in usedPositions: # Take a new line if current one is taken
input.seek(random.randrange(inputSize))
input.readline()
usedPositions.append(input.tell()) # Add line start position to usedPositions
randomLine=input.readline() # Complete line
if len(randomLine) == 0: # Take first line if end of the file is reached
input.seek(0)
for i in range(int(options.header)): # Exclude headers
input.readline()
randomLine=input.readline()
output.write(randomLine)
这段代码似乎工作正常。
我知道这段代码更喜欢输入中最长行之后的行,因为 seek() 最有可能返回最长行上的位置,并且下一行被写入输出。这无关紧要,因为输入文件中的行长度大致相同。我也知道如果 N 大于输入文件中的行数,此代码会导致无限循环。我不会对此进行检查,因为获取行数需要很多时间。
RAM 和 HDD 限制无关紧要。我只关心程序的速度。有没有办法进一步优化这段代码?或者也许有更好的方法?
编辑:澄清一下,一个文件中的行长度大致相同。但是,我有多个文件需要运行此脚本,并且这些文件的平均行长度会有所不同。例如,文件 A 每行可能有 ~100 个字符,文件 B 每行可能有 ~50000 个字符。我事先不知道任何文件的平均行长。