在Python中从文件(但不是全部)读取n行

时间:2010-12-03 02:56:23

标签: python file

如何在迭代文件时从文件中读取n行而不是一行?我有一个具有明确定义结构的文件,我想做这样的事情:

for line1, line2, line3 in file:
    do_something(line1)
    do_something_different(line2)
    do_something_else(line3)

但它不起作用:

  

ValueError:要解压缩的值太多

现在我这样做:

for line in file:
    do_someting(line)
    newline = file.readline()
    do_something_else(newline)
    newline = file.readline()
    do_something_different(newline)
... etc.

这很糟糕,因为我正在编写无休止的“newline = file.readline()”,这些代码混乱了。 有没有聪明的方法来做到这一点? (我真的想避免立刻阅读整个文件,因为它很大)

11 个答案:

答案 0 :(得分:4)

基本上,您的file是一个迭代器,它一次产生一行文件。这会将您的问题转化为如何从迭代器一次产生多个项目。 this question给出了解决方案。请注意,函数islice位于itertools模块中,因此您必须从那里导入它。

答案 1 :(得分:3)

如果是xml,为什么不直接使用lxml?

答案 2 :(得分:2)

您可以使用这样的辅助函数:

def readnlines(f, n):
    lines = []
    for x in range(0, n):
        lines.append(f.readline())
    return lines

然后你可以做你想做的事情:

while True:
    line1, line2, line3 = readnlines(file, 3)
    do_stuff(line1)
    do_stuff(line2)
    do_stuff(line3)

话虽如此,如果您使用的是xml文件,如果使用真正的xml解析器,从长远来看,您可能会更开心......

答案 3 :(得分:2)

itertools救援:

import itertools
def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)


fobj= open(yourfile, "r")
for line1, line2, line3 in grouper(3, fobj):
    pass

答案 4 :(得分:1)

for i in file生成str,因此您不能只执行for i, j, k in file并分三批阅读(尝试a, b, c = 'bar'a, b, c = 'too many characters'并查看在a,b和c的值处找出为什么你得到“太多的值来解包”。)

目前尚不清楚你的意思,但是如果你为每一行做同样的事情而只是想在某个时刻停下来,那么就这样做:

for line in file_handle:
    do_something(line)
    if some_condition:
        break  # Don't want to read anything else

(另外,不要使用file作为变量名称,而是对内置函数进行着色。)

答案 5 :(得分:0)

如果您正在做同样的事情,为什么每次迭代需要处理多行?

对于文件中的行是你的朋友。在操作性能和内存方面,它通常比手动读取文件更有效。

答案 6 :(得分:0)

您对数据的行/格式的长度有所了解吗?如果是这样,您可以读取前n个字节(例如80 * 3)和f.read(240).split(“\ n”)[0:3]。

答案 7 :(得分:0)

如果您希望能够一遍又一遍地使用这些数据,可能会采用以下方法:

lines = []
for line in file_handle:
    lines.append(line)

这将为您提供行列表,然后您可以通过索引访问这些行。另外,当你说一个巨大的文件时,它的大小很可能是微不足道的,因为python可以很快地处理数千行。

答案 8 :(得分:0)

为什么你不能这样做:

ctr = 0

for line in file:

  if ctr == 0:

     ....

  elif ctr == 1:

     ....

  ctr = ctr + 1

如果你发现if / elif构造很难看,你可以创建一个哈希表或函数指针列表,然后执行:

for line in file:

   function_list[ctr]()

或类似的东西

答案 9 :(得分:0)

听起来你正在尝试并行读取磁盘......这真的很难做到。给予您的所有解决方案都是现实和合法的。你不应该因为代码“看起来很难看”而让某些事情让你失望。最重要的是它是多么高效/有效,那么如果代码混乱,你可以整理它,但不要寻找一种全新的做法,因为你不喜欢一种方法在代码中看起来像。

至于内存不足,您可能需要查看pickle

答案 10 :(得分:0)

聪明地使用zip功能可以做到这一点。它很短,但有点巫术 - 我的口味(很难看出它是如何工作的)。它会切断最后一些不填充组的行,这可能是好的还是坏的,这取决于你正在做什么。如果您需要最后一行,itertools.izip_longest可能会成功。

zip(*[iter(inputfile)] * 3)

更明确,更灵活地做到这一点,这是对Mats Ekberg解决方案的修改:

def groupsoflines(f, n):
    while True:
        group = []
        for i in range(n):
            try:
                group.append(next(f))
            except StopIteration:
                if group:
                    tofill = n - len(group)
                    yield group + [None] * tofill
                return
        yield group

for line1, line2, line3 in groupsoflines(inputfile, 3):
    ...

N.B。如果在组中途没有线条,则会填充None的间隙,这样您仍然可以解压缩它。因此,如果文件中的行数可能不是三的倍数,则需要检查line2line3None