A bit modified version of a great Mechanical snail's answer. Here, readinto(b)
implementation makes multiple calls to the the underlying iterator, in order to gather as much as possible amount of bytes for the size of the given writable bytes-like object b
.
class IteratorReader(io.RawIOBase):
def __init__(self, iterator):
self.iterator = iterator
self.leftover = []
def readinto(self, buffer: bytearray) -> Optional[int]:
size = len(buffer)
while len(self.leftover) < size:
try:
self.leftover.extend(next(self.iterator))
except StopIteration:
break
if len(self.leftover) == 0:
return 0
output, self.leftover = self.leftover[:size], self.leftover[size:]
buffer[:len(output)] = output
return len(output)
def readable(self) -> bool:
return True
and usage:
def iterator1():
for i in ('a', 'b', 'c', 'd', 'e', 'f', 'g'):
res = i * 3
yield res.encode("utf8")
iterreader = IteratorReader(iterator1())
while True:
r = iterreader.read(4)
if not r:
break
print(r)
stream = io.StringIO("".join(make_file()))
? – Abhorrencemake_file()
may return a large file, and I'd rather not load it into memory. – Jobey