Python urllib2 Progress Hook

Estoy intentando crear una barra de progreso de descarga en Python utilizando el cliente http urllib2. He mirado a través de la API (y en google) y parece que urllib2 no le permite registrar ganchos de progreso. Sin embargo, el antiguo urllib en desuso tiene esta funcionalidad.

¿Alguien sabe cómo crear una barra de progreso o un gancho de reporte usando urllib2? ¿O hay algunos otros hacks para obtener una funcionalidad similar?

Aquí hay un ejemplo completamente funcional que se basa en el enfoque de Anurag de fragmentar en una respuesta. Mi versión le permite establecer el tamaño del fragmento y adjuntar una función de informe arbitraria:

import urllib2, sys def chunk_report(bytes_so_far, chunk_size, total_size): percent = float(bytes_so_far) / total_size percent = round(percent*100, 2) sys.stdout.write("Downloaded %d of %d bytes (%0.2f%%)\r" % (bytes_so_far, total_size, percent)) if bytes_so_far >= total_size: sys.stdout.write('\n') def chunk_read(response, chunk_size=8192, report_hook=None): total_size = response.info().getheader('Content-Length').strip() total_size = int(total_size) bytes_so_far = 0 while 1: chunk = response.read(chunk_size) bytes_so_far += len(chunk) if not chunk: break if report_hook: report_hook(bytes_so_far, chunk_size, total_size) return bytes_so_far if __name__ == '__main__': response = urllib2.urlopen('http://www.ebay.com'); chunk_read(response, report_hook=chunk_report) 

¿Por qué no solo leer los datos en fragmentos y hacer lo que quiera hacer en el medio, por ejemplo, ejecutar en un hilo, enganchar en una interfaz de usuario, etc.?

 import urllib2 urlfile = urllib2.urlopen("http://www.google.com") data_list = [] chunk = 4096 while 1: data = urlfile.read(chunk) if not data: print "done." break data_list.append(data) print "Read %s bytes"%len(data) 

salida :

 Read 4096 bytes Read 3113 bytes done. 

urlgrabber tiene soporte incorporado para la notificación de progreso.

Versión simplificada:

 temp_filename = "/tmp/" + file_url.split('/')[-1] f = open(temp_filename, 'wb') remote_file = urllib2.urlopen(file_url) try: total_size = remote_file.info().getheader('Content-Length').strip() header = True except AttributeError: header = False # a response doesn't always include the "Content-Length" header if header: total_size = int(total_size) bytes_so_far = 0 while True: buffer = remote_file.read(8192) if not buffer: sys.stdout.write('\n') break bytes_so_far += len(buffer) f.write(buffer) if not header: total_size = bytes_so_far # unknown size percent = float(bytes_so_far) / total_size percent = round(percent*100, 2) sys.stdout.write("Downloaded %d of %d bytes (%0.2f%%)\r" % (bytes_so_far, total_size, percent))