我正在阅读一个大文件并进行处理。 我希望能够在不花费很长时间的情况下跳到文件的中间。
现在我正在做:
f = gzip.open(input_name)
for i in range(1000000):
f.read() # just skipping the first 1M rows
for line in f:
do_something(line)
有没有更快的方法来跳过压缩文件中的行? 如果我必须首先解压缩,我会这样做,但必须有办法。
它当然是一个文本文件,\n
分隔行。
答案 0 :(得分:9)
gzipping的本质是当文件被压缩时不再存在行的概念 - 它只是一个二进制blob。查看this,了解gzip的功能。
要读取文件,您需要对其进行解压缩 - gzip
模块可以很好地解决它。与其他答案一样,我也建议itertools
进行跳跃,因为它会仔细确保您不会将内容拉入内存,它会尽快让您到达目的地。 / p>
with gzip.open(filename) as f:
# jumps to `initial_row`
for line in itertools.slice(f, initial_row, None):
# have a party
或者,如果这是您正在使用的CSV,您还可以尝试计时pandas
解析,因为它可以处理解压缩gzip
。这看起来像是:parsed_csv = pd.read_csv(filename, compression='gzip')
。
另外,要进一步明确,当您在python中迭代文件对象时 - 例如上面的f
变量 - 您将遍历行。你不需要考虑' \ n'字符。
答案 1 :(得分:3)
您可以使用itertools.islice,传递文件对象f
和起始点,它仍然可以推进迭代器,但比调用下一次1000000次更有效:
from itertools import islice
for line in islice(f,1000000,None):
print(line)
并不过分熟悉gzip,但我想f.read()
读取整个文件,以便接下来的999999次调用无效。如果你想手动推进迭代器,你可以在文件对象上调用next,即next(f)
。
调用next(f)
并不意味着所有行都会立即被读入内存,它会一次使迭代器前进一行,所以如果你想在文件或标题中跳过一行或两行可能很有用。
{@ 3}}食谱作为@wwii建议食谱也值得一试
答案 2 :(得分:1)
不是。
如果您知道要跳过的字节数,可以在文件对象上使用.seek(amount)
,但为了跳过多行,Python必须逐字节地遍历文件才能计算换行符。
我想到的唯一选择是你处理某个静态文件,这个文件不会改变。在这种情况下,您可以将其编入索引一次,即找出并记住每一行的位置。如果你有这样的话您使用pickle
保存并加载的字典,您可以使用seek
在准恒定时间内跳过该字典。
答案 3 :(得分:1)
无法在gzip文件中随机搜索。 Gzip是一种流算法,因此必须始终从一开始就解压缩,直到您感兴趣的数据所在。
如果没有索引,则无法跳转到特定行。可以向前扫描行或从文件末尾以连续块的形式向后扫描。
您应该根据需要考虑不同的存储格式。你有什么需求?