Index: Doc/library/urllib.request.rst =================================================================== --- Doc/library/urllib.request.rst (revision 67649) +++ Doc/library/urllib.request.rst (working copy) @@ -80,7 +80,7 @@ A :class:`BaseHandler` subclass may also change its :attr:`handler_order` member variable to modify its position in the handlers list. -.. function:: urlretrieve(url[, filename[, reporthook[, data]]]) +.. function:: urlretrieve(url[, filename[, reporthook[, data[, progresshook]]]]) Copy a network object denoted by a URL to a local file, if necessary. If the URL points to a local file, or a valid cached copy of the object exists, the object @@ -97,7 +97,9 @@ thereafter. The hook will be passed three arguments; a count of blocks transferred so far, a block size in bytes, and the total size of the file. The third argument may be ``-1`` on older FTP servers which do not return a file - size in response to a retrieval request. + size in response to a retrieval request. *progresshook* behaves like + *reporthook* but will be passed two arguments: number of bytes read and total + size of the file (or ``-1``). If the *url* uses the :file:`http:` scheme identifier, the optional *data* argument may be given to specify a ``POST`` request (normally the request type Index: Lib/urllib/request.py =================================================================== --- Lib/urllib/request.py (revision 67649) +++ Lib/urllib/request.py (working copy) @@ -127,11 +127,11 @@ # TODO(jhylton): Make this work with the same global opener. _urlopener = None -def urlretrieve(url, filename=None, reporthook=None, data=None): +def urlretrieve(url, filename=None, reporthook=None, data=None, progresshook=None): global _urlopener if not _urlopener: _urlopener = FancyURLopener() - return _urlopener.retrieve(url, filename, reporthook, data) + return _urlopener.retrieve(url, filename, reporthook, data, progresshook) def urlcleanup(): if _urlopener: @@ -1458,7 +1458,7 @@ raise IOError('url error', 'invalid proxy for %s' % type, proxy) # External interface - def retrieve(self, url, filename=None, reporthook=None, data=None): + def retrieve(self, url, filename=None, reporthook=None, data=None, progresshook=None): """retrieve(url) returns (filename, headers) for a local object or (tempfilename, headers) for a remote object.""" url = unwrap(to_bytes(url)) @@ -1494,10 +1494,12 @@ size = -1 read = 0 blocknum = 0 + if "content-length" in headers: + size = int(headers["Content-Length"]) if reporthook: - if "content-length" in headers: - size = int(headers["Content-Length"]) reporthook(blocknum, bs, size) + if progresshook: + progresshook(read, size) while 1: block = fp.read(bs) if not block: @@ -1507,6 +1509,8 @@ blocknum += 1 if reporthook: reporthook(blocknum, bs, size) + if progresshook: + progresshook(read, size) fp.close() tfp.close() del fp