如何在Python中循环直到EOF?
我需要循环,直到到达类似文件的对象的末尾,但我没有找到“明显的方法”,这让我怀疑我忽略了一些明显的东西。 :-)
我有一个流(在本例中,它是一个 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 的语言中,我只需坚持while
的测试子句中的 read(4)
,但这当然不适用于 Python。关于更好的方法来实现这一目标有什么想法吗?
I need to loop until I hit the end of a file-like object, but I'm not finding an "obvious way to do it", which makes me suspect I'm overlooking something, well, obvious. :-)
I have a stream (in this case, it's a StringIO object, but I'm curious about the general case as well) which stores an unknown number of records in "<length><data>" format, e.g.:
data = StringIO("\x07\x00\x00\x00foobar\x00\x04\x00\x00\x00baz\x00")
Now, the only clear way I can imagine to read this is using (what I think of as) an initialized loop, which seems a little un-Pythonic:
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)
In a C-like language, I'd just stick the read(4)
in the while
's test clause, but of course that won't work for Python. Any thoughts on a better way to accomplish this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(6)
正如预测的那样,我看到典型且最流行的答案是使用非常专业的生成器“一次读取 4 个字节”。有时,通用性并不困难(而且更有价值;-),因此,我建议采用以下非常通用的解决方案:
import operator
def funlooper(afun, *a, **k):
wearedone = k.pop('wearedone', operator.not_)
while True:
data = afun(*a, **k)
if wearedone(data): break
yield data
现在您想要的循环标头只是: for len_name in funlooper(data.read, 4 ):
。
编辑:通过 wearedone
惯用法变得更加通用,因为有评论指责我不太通用的先前版本(将退出测试硬编码为 if not data:
) 拥有“隐藏的依赖”,所有的事情!-)
通常的瑞士军刀循环, itertools
,当然也可以,像往常一样:
import itertools as it
for len_name in it.takewhile(bool, it.imap(data.read, it.repeat(4))): ...
或者,相当等效:
import itertools as it
def loop(pred, fun, *args):
return it.takewhile(pred, it.starmap(fun, it.repeat(args)))
for len_name in loop(bool, data.read, 4): ...
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
您可以将通过 iter() 的迭代与哨兵结合起来:
You can combine iteration through iter() with a sentinel: