如何在Python中循环直到EOF?

11 投票
6 回答
69163 浏览
提问于 2025-04-15 16:07

我需要循环读取一个像文件一样的对象,直到到达文件的末尾,但我找不到一个“明显的方法”,这让我觉得我可能忽略了什么简单的东西。:-)

我有一个流(在这个例子中,它是一个StringIO对象,但我也对一般情况感兴趣),这个流以“<长度><数据>”的格式存储了不确定数量的记录,比如:

data = StringIO("\x07\x00\x00\x00foobar\x00\x04\x00\x00\x00baz\x00")

现在,我能想到的唯一清晰的读取方法是使用(我认为是)一个初始化的循环,这看起来有点不符合Python的风格:

len_name = data.read(4)

while len_name != "":
    len_name = struct.unpack("<I", len_name)[0]
    names.append(data.read(len_name))

    len_name = data.read(4)

在像C这样的语言中,我只需把read(4)放在while的测试条件里,但当然这在Python中行不通。你有什么更好的方法来实现这个吗?

6 个回答

6

我更喜欢之前提到的基于迭代器的方案,把这个变成一个for循环。还有一种直接写的解决方案是Knuth的“半循环”方法。

while 1:
    len_name = data.read(4)
    if not len_name:
        break
    names.append(data.read(len_name))

你可以通过对比看到,这个方法很容易被提取成一个独立的生成器,然后用作for循环。

10

你知道怎么逐行读取一个文本文件吗?

for line in file_obj:
  use(line)

你也可以用自己的生成器来做到这一点:

def read_blocks(file_obj, size):
  while True:
    data = file_obj.read(size)
    if not data:
      break
    yield data

for block in read_blocks(file_obj, 4):
  use(block)

另外,你可以看看:

27

你可以把使用 iter() 这个函数进行循环和一个哨兵值结合起来:

for block in iter(lambda: file_obj.read(4), ""):
  use(block)

撰写回答