Index: Lib/io.py =================================================================== --- Lib/io.py (revision 67439) +++ Lib/io.py (working copy) @@ -1045,7 +1045,18 @@ # XXX Why not just let the exception pass through? raise BlockingIOError(e.errno, e.strerror, 0) before = len(self._write_buf) - self._write_buf.extend(b) + bytes_to_consume = self.max_buffer_size - before + # b is an iterable of ints, it won't always support len(). + if hasattr(b, '__len__') and len(b) > bytes_to_consume: + # Avoid an extra data copy if possible. + try: + data = memoryview(b)[:bytes_to_consume] + except TypeError: + # No buffer API? slice into a temporary copy. + data = b[:bytes_to_consume] + self._write_buf.extend(data) + else: + self._write_buf.extend(b) written = len(self._write_buf) - before if len(self._write_buf) > self.buffer_size: try: Index: Lib/test/test_io.py =================================================================== --- Lib/test/test_io.py (revision 67439) +++ Lib/test/test_io.py (working copy) @@ -425,7 +425,9 @@ random.shuffle(l) s = bytes(bytearray(l)) with io.open(support.TESTFN, "wb") as f: - f.write(s) + idx = 0 + while idx < len(s): + idx += f.write(memoryview(s)[idx:]) with io.open(support.TESTFN, "rb", buffering=0) as raw: bufio = io.BufferedReader(raw, 8) errors = []