如何在迭代文件时从文件中读取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()
”,这些代码混乱了。
有没有聪明的方法来做到这一点? (我真的想避免立刻阅读整个文件,因为它很大)
答案 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
的间隙,这样您仍然可以解压缩它。因此,如果文件中的行数可能不是三的倍数,则需要检查line2
和line3
是None
。