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

在Python中从文件(但不是全部)读取n行,python,file,Python,File,如何从一个文件中读取n行而不是一行?我有一个结构定义良好的文件,我想做如下工作: for line1, line2, line3 in file: do_something(line1) do_something_different(line2) do_something_else(line3) for line in file_handle: do_something(line) if some_condition: break #

如何从一个文件中读取n行而不是一行?我有一个结构定义良好的文件,我想做如下工作:

for line1, line2, line3 in file:
    do_something(line1)
    do_something_different(line2)
    do_something_else(line3)
for line in file_handle:
    do_something(line)
    if some_condition:
        break  # Don't want to read anything else
def readnlines(f, n):
    lines = []
    for x in range(0, n):
        lines.append(f.readline())
    return lines
但它不起作用:

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()
”,它们把代码弄得乱七八糟。
有什么聪明的方法可以做到这一点吗?(我真的不想一次读取整个文件,因为它太大了)

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


因为文件中的行是您的朋友。在io性能和内存方面,它通常比手动读取文件要高效得多。

for i in file
生成一个
str
,因此您不能只对文件中的i、j、k执行
,然后分三批读取它(尝试
a,b,c='bar'
a,b,c='too many characters'
并查看a,b和c的值,找出为什么会出现“太多的值需要解包”)

你的意思并不完全清楚,但如果你对每一行都做同样的事情,只是想在某个点停下来,那么就这样做:

for line1, line2, line3 in file:
    do_something(line1)
    do_something_different(line2)
    do_something_else(line3)
for line in file_handle:
    do_something(line)
    if some_condition:
        break  # Don't want to read anything else
def readnlines(f, n):
    lines = []
    for x in range(0, n):
        lines.append(f.readline())
    return lines

(另外,不要使用
文件
作为变量名,这是在隐藏一个内置项。)

您知道行的长度/数据的格式吗?如果知道,您可以读取前n个字节(比如80*3)和f.read(240)。拆分(“\n”)[0:3].

如果您希望能够反复使用此数据,一种方法可能是:

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

这将为您提供一个行列表,您可以通过索引访问这些行。此外,当您说一个大文件时,它的大小很可能无关紧要,因为python可以非常快速地处理数千行。

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

为什么您不能这样做:

ctr=0

对于文件中的行:

  if ctr == 0:

     ....

  elif ctr == 1:

     ....

  ctr = ctr + 1
   function_list[ctr]()
如果发现if/elif构造很难看,可以创建一个哈希表或函数指针列表,然后执行以下操作:

对于文件中的行:

  if ctr == 0:

     ....

  elif ctr == 1:

     ....

  ctr = ctr + 1
   function_list[ctr]()

或者类似的

您可以使用如下帮助函数:

for line1, line2, line3 in file:
    do_something(line1)
    do_something_different(line2)
    do_something_else(line3)
for line in file_handle:
    do_something(line)
    if some_condition:
        break  # Don't want to read anything else
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解析器,您可能会更高兴…

基本上,您的
文件是一个迭代器,一次生成一行文件。这将把您的问题转化为如何从迭代器一次生成多个项目。中给出了解决方案。不是e函数
islice
在itertools模块中,因此您必须从那里导入它。

听起来您试图从磁盘并行读取数据……这真的很难做到。提供给您的所有解决方案都是现实和合法的。您不应该因为代码“看起来很难看”而让某些东西拖了您的后腿.最重要的是它的效率/效果如何,那么如果代码凌乱,你可以整理它,但不要寻找一种全新的方法来做某事,因为你不喜欢代码中的一种方法


至于内存不足,您可能想退出。

可以通过巧妙地使用zip功能来实现。它很短,但对我的口味来说有点巫毒(很难看出它是如何工作的)。它会在末尾截断所有未填充组的行,这可能是好的,也可能是坏的,这取决于您正在做什么。如果您需要最后一行,
itertools.izip\u 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):
    ...
注意:如果该文件在一个组的中途用完了行,它将用
None
来填补空白,这样您仍然可以将其解压缩。因此,如果文件中的行数可能不是三的倍数,您需要检查
line2
line3
是否为
None
,以帮助:

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

不幸的是,这是一个类似xml的巨大文件,其中的一些值可能有不同的长度。大文件是最大的文件?10K?1MB?100MB?我想它太大了,无法读取整个文件,但即使读取100K也很便宜/快。除非你必须在一个紧凑的循环中执行一百万次。我现在拥有的文件是80mb,我可能会有更大的文件在未来,我不想绕过这个问题,把整个事情加载到内存中,因为这个特殊的问题经常出现(至少对我来说):你会考虑发布这个文件的一个可能被消毒的样本吗?根据结构,你可以考虑一些事情。我只想简单的方法一次读几行;文件的结构在这里并不重要,我需要为这个似乎是基本任务的语言构造。我给出的代码(newline=readline())正在完成这项工作,它既难看又长。我想知道写这篇文章的“pythonic”方式是什么。对不起,编辑,我想对n行中的每一行做不同的事情,然后对另一批n文件中的行做相同的事情我不想反复使用这些数据;我想读10行;对他们做10件不同的事情,然后再读10行并重复,等等。在我看来,这仍然是选择的方法。如果你在一个方法中进行数据操作,并将列表放在其中,它将被垃圾收集器清除,因此这不会占用过多的内存,并且你可以按任何顺序访问任何你想要的索引。这个方法是不可能的,因为我不想编写如果文件大于内存大小就会崩溃的代码。如果我们每次都能将文件加载到列表中,那么根本就不会有文件数据类型或readline(),只有readall和put-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-into-。这不是做事情的方式,因为我在字符串上做非常简单的操作,我不需要一个解析器来读取所有的标签等。;我只想先做一个