What I usually do:
def unpack(stream, fmt): size = struct.calcsize(fmt) buf = stream.read(size) return struct.unpack(fmt, buf)
For instance:
>>> b = io.BytesIO(b'\n\x00\x02\x90\x10\x00\n\x00\x02`\x10\x00\n\x00\x02\x80\x10\x00') >>> print(unpack(b, '>I')) (167772816,) >>> print(unpack(b, '>I')) (268438016,) >>> print(unpack(b, '>I')) (39849984,) >>> print(unpack(b, '>I')) (167772800,) >>> print(unpack(b, '>H')) (4096,)
If you want to know if you are consuming the entire stream, you can always do this:
buf = stream.read(1) if buf: raise ValueError("Stream not consumed")
But it is probably easier to just call the same function that you are already using:
>>> def ensure_finished(stream): ... try: ... unpack(stream, 'c') ... except struct.error: ... pass ... else: ... raise ValueError('Stream not consumed') >>> ensure_finished(b)
If you use a stream that can read less than the requested number of bytes, you want to use a while to continue reading and adding to EOF or to get enough bytes. Otherwise, thatโs all you need.
source share