bpo-36050: optimize HTTPResponse.read() (GH-12698)
* No need to chunking for now. * No need to partial read caused by EINTR for now.
This commit is contained in:
parent
a0da131a74
commit
d6bf6f2d0c
|
@ -105,9 +105,6 @@ globals().update(http.HTTPStatus.__members__)
|
||||||
# Mapping status codes to official W3C names
|
# Mapping status codes to official W3C names
|
||||||
responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()}
|
responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()}
|
||||||
|
|
||||||
# maximal amount of data to read at one time in _safe_read
|
|
||||||
MAXAMOUNT = 1048576
|
|
||||||
|
|
||||||
# maximal line length when calling readline().
|
# maximal line length when calling readline().
|
||||||
_MAXLINE = 65536
|
_MAXLINE = 65536
|
||||||
_MAXHEADERS = 100
|
_MAXHEADERS = 100
|
||||||
|
@ -592,43 +589,24 @@ class HTTPResponse(io.BufferedIOBase):
|
||||||
raise IncompleteRead(bytes(b[0:total_bytes]))
|
raise IncompleteRead(bytes(b[0:total_bytes]))
|
||||||
|
|
||||||
def _safe_read(self, amt):
|
def _safe_read(self, amt):
|
||||||
"""Read the number of bytes requested, compensating for partial reads.
|
"""Read the number of bytes requested.
|
||||||
|
|
||||||
Normally, we have a blocking socket, but a read() can be interrupted
|
|
||||||
by a signal (resulting in a partial read).
|
|
||||||
|
|
||||||
Note that we cannot distinguish between EOF and an interrupt when zero
|
|
||||||
bytes have been read. IncompleteRead() will be raised in this
|
|
||||||
situation.
|
|
||||||
|
|
||||||
This function should be used when <amt> bytes "should" be present for
|
This function should be used when <amt> bytes "should" be present for
|
||||||
reading. If the bytes are truly not available (due to EOF), then the
|
reading. If the bytes are truly not available (due to EOF), then the
|
||||||
IncompleteRead exception can be used to detect the problem.
|
IncompleteRead exception can be used to detect the problem.
|
||||||
"""
|
"""
|
||||||
s = []
|
data = self.fp.read(amt)
|
||||||
while amt > 0:
|
if len(data) < amt:
|
||||||
chunk = self.fp.read(min(amt, MAXAMOUNT))
|
raise IncompleteRead(data, amt-len(data))
|
||||||
if not chunk:
|
return data
|
||||||
raise IncompleteRead(b''.join(s), amt)
|
|
||||||
s.append(chunk)
|
|
||||||
amt -= len(chunk)
|
|
||||||
return b"".join(s)
|
|
||||||
|
|
||||||
def _safe_readinto(self, b):
|
def _safe_readinto(self, b):
|
||||||
"""Same as _safe_read, but for reading into a buffer."""
|
"""Same as _safe_read, but for reading into a buffer."""
|
||||||
total_bytes = 0
|
amt = len(b)
|
||||||
mvb = memoryview(b)
|
n = self.fp.readinto(b)
|
||||||
while total_bytes < len(b):
|
if n < amt:
|
||||||
if MAXAMOUNT < len(mvb):
|
raise IncompleteRead(bytes(b[:n]), amt-n)
|
||||||
temp_mvb = mvb[0:MAXAMOUNT]
|
return n
|
||||||
n = self.fp.readinto(temp_mvb)
|
|
||||||
else:
|
|
||||||
n = self.fp.readinto(mvb)
|
|
||||||
if not n:
|
|
||||||
raise IncompleteRead(bytes(mvb[0:total_bytes]), len(b))
|
|
||||||
mvb = mvb[n:]
|
|
||||||
total_bytes += n
|
|
||||||
return total_bytes
|
|
||||||
|
|
||||||
def read1(self, n=-1):
|
def read1(self, n=-1):
|
||||||
"""Read with at most one underlying system call. If at least one
|
"""Read with at most one underlying system call. If at least one
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Optimized ``http.client.HTTPResponse.read()`` for large response. Patch by
|
||||||
|
Inada Naoki.
|
Loading…
Reference in New Issue