Fixes issue #6838: use a list to accumulate the value instead of repeatedly concatenating strings.

This commit is contained in:
Chris Withers 2009-09-04 17:15:46 +00:00
parent 04ee867b6d
commit 5a86acb6d6
2 changed files with 14 additions and 12 deletions

View File

@ -518,10 +518,7 @@ class HTTPResponse(io.RawIOBase):
def _read_chunked(self, amt): def _read_chunked(self, amt):
assert self.chunked != _UNKNOWN assert self.chunked != _UNKNOWN
chunk_left = self.chunk_left chunk_left = self.chunk_left
value = b"" value = []
# XXX This accumulates chunks by repeated string concatenation,
# which is not efficient as the number or size of chunks gets big.
while True: while True:
if chunk_left is None: if chunk_left is None:
line = self.fp.readline() line = self.fp.readline()
@ -534,22 +531,22 @@ class HTTPResponse(io.RawIOBase):
# close the connection as protocol synchronisation is # close the connection as protocol synchronisation is
# probably lost # probably lost
self.close() self.close()
raise IncompleteRead(value) raise IncompleteRead(b''.join(value))
if chunk_left == 0: if chunk_left == 0:
break break
if amt is None: if amt is None:
value += self._safe_read(chunk_left) value.append(self._safe_read(chunk_left))
elif amt < chunk_left: elif amt < chunk_left:
value += self._safe_read(amt) value.append(self._safe_read(amt))
self.chunk_left = chunk_left - amt self.chunk_left = chunk_left - amt
return value return b''.join(value)
elif amt == chunk_left: elif amt == chunk_left:
value += self._safe_read(amt) value.append(self._safe_read(amt))
self._safe_read(2) # toss the CRLF at the end of the chunk self._safe_read(2) # toss the CRLF at the end of the chunk
self.chunk_left = None self.chunk_left = None
return value return b''.join(value)
else: else:
value += self._safe_read(chunk_left) value.append(self._safe_read(chunk_left))
amt -= chunk_left amt -= chunk_left
# we read the whole chunk, get another # we read the whole chunk, get another
@ -570,7 +567,7 @@ class HTTPResponse(io.RawIOBase):
# we read everything; close the "file" # we read everything; close the "file"
self.close() self.close()
return value return b''.join(value)
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, compensating for partial reads.

View File

@ -50,6 +50,11 @@ C-API
Library Library
------- -------
- Issue #6838: Use a list to accumulate the value instead of
repeatedly concatenating strings in http.client's
HTTPResponse._read_chunked providing a significant speed increase
when downloading large files servend with a Transfer-Encoding of 'chunked'.
- Have importlib raise ImportError if None is found in sys.modules for a - Have importlib raise ImportError if None is found in sys.modules for a
module. module.