Pregunta

Estoy escribiendo una pequeña aplicación para descargar archivos a través de http (como, por ejemplo, se describe aquí).

También quiero incluir un pequeño indicador de progreso de descarga que muestre el porcentaje del progreso de descarga.

Esto es lo que se me ocurrió:

    sys.stdout.write(rem_file + "...")    
    urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress)

    def dlProgress(count, blockSize, totalSize):
      percent = int(count*blockSize*100/totalSize)
      sys.stdout.write("%2d%%" % percent)
      sys.stdout.write("\b\b\b")
      sys.stdout.flush()

Producción:MiNombreDeArchivo...9%

¿Alguna otra idea o recomendación para hacer esto?

Una cosa que resulta algo molesta es el cursor parpadeante en el terminal sobre el primer dígito del porcentaje.¿Hay alguna manera de prevenir esto?¿Hay alguna manera de ocultar el cursor?

EDITAR:

Aquí hay una mejor alternativa usando una variable global para el nombre del archivo en dlProgress y el código ' ':

    global rem_file # global variable to be used in dlProgress

    urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress)

    def dlProgress(count, blockSize, totalSize):
      percent = int(count*blockSize*100/totalSize)
      sys.stdout.write("\r" + rem_file + "...%d%%" % percent)
      sys.stdout.flush()

Producción:MiNombreDeArchivo...9%

Y el cursor aparece al FINAL de la línea.Mucho mejor.

¿Fue útil?

Solución

Hay una biblioteca de barra de progreso de texto para Python en http://pypi.python.org/pypi/progressbar/2.2 que te puede resultar útil:

Esta biblioteca proporciona una barra de progreso en modo texto.Normalmente se utiliza para mostrar el progreso de una operación de larga duración, proporcionando una pista visual de que el procesamiento está en marcha.

La clase ProgressBar gestiona el progreso y el formato de la línea viene dado por varios widgets.Un widget es un objeto que puede mostrarse de manera diferente según el estado del progreso.Hay tres tipos de widgets:- una cuerda, que siempre se muestra;- un ProgressBarWidget, que puede devolver un valor diferente cada vez que se llama a su método de actualización;y - un ProgressBarWidgetHFill, que es como ProgressBarWidget, excepto que se expande para llenar el ancho restante de la línea.

El módulo de barra de progreso es muy fácil de usar, pero muy potente.Y admite automáticamente funciones como el cambio de tamaño automático cuando esté disponible.

Otros consejos

También puedes intentar:

sys.stdout.write("\r%2d%%" % percent)
sys.stdout.flush()

Usar un solo retorno de carro al comienzo de la cadena en lugar de varios retrocesos.El cursor seguirá parpadeando, pero parpadeará después del signo de porcentaje en lugar de debajo del primer dígito, y con un carácter de control en lugar de tres es posible que el parpadeo sea menor.

Por si sirve de algo, aquí está el código que utilicé para que funcione:

from urllib import urlretrieve
from progressbar import ProgressBar, Percentage, Bar

url = "http://......."
fileName = "file"
pbar = ProgressBar(widgets=[Percentage(), Bar()])
urlretrieve(url, fileName, reporthook=dlProgress)

def dlProgress(count, blockSize, totalSize):
    pbar.update( int(count * blockSize * 100 / totalSize) )

Si usas el curses paquete, tienes mucho mayor control de la consola.También tiene un costo mayor en complejidad del código y probablemente sea innecesario a menos que esté desarrollando una aplicación grande basada en consola.

Para una solución sencilla, siempre puedes poner la rueca al final del mensaje de estado (la secuencia de caracteres |, \, -, / que en realidad se ve bien bajo el cursor parpadeante.

Usé este código:

url = (<file location>)
file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)

file_size_dl = 0
block_sz = 8192
while True:
    buffer = u.read(block_sz)
    if not buffer:
        break

    file_size_dl += len(buffer)
    f.write(buffer)
    status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
    status = status + chr(8)*(len(status)+1)
    print status,

f.close()
def download_progress_hook(count, blockSize, totalSize):
  """A hook to report the progress of a download. This is mostly intended for users with slow internet connections. Reports every 5% change in download progress.
  """
  global last_percent_reported
  percent = int(count * blockSize * 100 / totalSize)

  if last_percent_reported != percent:
    if percent % 5 == 0:
      sys.stdout.write("%s%%" % percent)
      sys.stdout.flush()
    else:
      sys.stdout.write(".")
      sys.stdout.flush()

    last_percent_reported = percent

urlretrieve(url, filename, reporthook=download_progress_hook)

Para archivos pequeños es posible que necesites tener estas líneas para evitar porcentajes locos:

sys.stdout.write(" %2d%%" % por ciento)

sys.stdout.flush()

Salud

Así es como lo hice, esto podría ayudarte:https://github.com/mouuff/MouDownloader/blob/master/api/download.py

Tarde a la fiesta, como siempre.Aquí hay una implementación que admite informes de progreso, como el núcleo. urlretrieve:

import urllib2

def urlretrieve(urllib2_request, filepath, reporthook=None, chunk_size=4096):
    req = urllib2.urlopen(urllib2_request)

    if reporthook:
        # ensure progress method is callable
        if hasattr(reporthook, '__call__'):
            reporthook = None

        try:
            # get response length
            total_size = req.info().getheaders('Content-Length')[0]
        except KeyError:
            reporthook = None

    data = ''
    num_blocks = 0

    with open(filepath, 'w') as f:
        while True:
            data = req.read(chunk_size)
            num_blocks += 1
            if reporthook:
                # report progress
                reporthook(num_blocks, chunk_size, total_size)
            if not data:
                break
            f.write(data)

    # return downloaded length
    return len(data)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top