Cómo imprimir "puntos" (u otro tipo de retroalimentación), mientras que la escritura de un archivo en python?

0

Pregunta

Estoy tratando de imprimir un visible de retroalimentación para el usuario en el terminal, mientras que mi aplicación donwloads un archivo desde la web y escribir en el disco duro, pero no podía encontrar la manera de hacer esta lectura de la documentación o googlear ella.

Este es mi código:

res = requests.get(url_to_file)
with open("./downloads/%s" % (file_name), 'wb') as f:
    f.write(res.content)

Yo estaba esperando a averiguar cómo hacer algo como esto:

Downloading file ........
 # it keeps going ultil the download is finished and the file writen
Done!

Estoy realmente strugling incluso para empezar, porque ninguno de los métodos devuelve una "promesa" (como en JS).

Cualquier ayuda sería muy apreciada! Gracias!

file promise python
2021-11-24 05:40:54
2

Mejor respuesta

3

requests.get por defecto de descargas de la totalidad del recurso solicitado antes de que llegue de nuevo a usted. Sin embargo, tiene un argumento opcional stream, que le permite invocar a .iter_content o .iter_lines en el Response objeto. Esto permite tomar medidas todos los N bytes (o como cada fragmento de datos llega), o en cada línea, respectivamente. Algo como esto:

chunks = []
chunk_size = 16384     # 16Kb chunks
# alternately
# chunk_size = None    # whenever a chunk arrives
res = requests.get(url_to_file, stream=True)
for chunk in res.iter_content(chunk_size):
    chunks.append(chunk)
    print(".", end="")
data = b''.join(chunks)

Esto bloquea, así que nada más va a estar sucediendo. Si quieres más de lo JavaScript estilo, por Grismar comentario, usted debe ejecutar con Python async bucle. En ese caso, sugiero el uso de aiohttp en lugar de requests, ya que es creado con async estilo en mente.

2021-11-24 06:52:04

Muchas gracias por tu respuesta! Fue muy rápido! jaja me hizo entienda el concepto y es bueno saber que hay async funciones en python. Por alguna razón, cuando traté de aplicar el código, sólo se imprimen los archivos después de que la solicitud haya terminado. Probablemente me estoy perdiendo algo...
guilfer
1

He aquí una versión que se descarga el archivo en un bytearray en un hilo separado.

Como se ha mencionado en otras respuestas y comentarios, hay otros alternativs que se desarrollan con las operaciones asincrónicas en mente, así que no leer demasiado en la decisión de ir con threadinges solo para demostrar el concepto (y debido a la comodidad, ya que viene con python).

En el siguiente código, si el tamaño del archivo es conocido, cada . le corresponde al 1%. Como un bono, la descarga y el número total de bytes que serán impresos en el inicio de la línea como (1234 B / 1234567 B). Si el tamaño no es conocido, la solución alternativa es que cada una de . representan una porción.

import requests
import threading


def download_file(url: str):
    headers = {"<some_key>": "<some_value>"}
    data = bytearray()
    with requests.get(url, headers=headers, stream=True) as request:
        if file_size := request.headers.get("Content-Length"):
            file_size = int(file_size)
        else:
            file_size = None
        received = 0
        for chunk in request.iter_content(chunk_size=2**15):
            received += len(chunk)
            data += chunk
            try:
                num_dots = int(received * 100 / file_size)
                print(
                    f"({received} B/{file_size} B) "
                    + "." * num_dots, end="\r"
                )
            except TypeError:
                print(".", end="")
        print("\nDone!")

url = "<some_url>"
thread = threading.Thread(target=download_file, args=(url,))
thread.start()
# Do something in the meantime
thread.join()

Tenga en cuenta que me he dejado la cerradura para proteger contra el acceso simultáneo a stdout para reducir el ruido. También he dejado fuera de la escritura de la bytarray para presentar al final (o de la escritura de los fragmentos de archivo a medida que se reciben si el archivo es grande), pero tenga en cuenta que puede que desee utilizar un bloqueo para que así si puedes leer y/o escribir en el mismo archivo en cualquier otra parte de su secuencia de comandos.

2021-11-24 05:57:53

Que es impresionante! Creo que entiendo el concepto, pero soy bastante nuevo en python y me decidí a ir por el camino fácil jaja yo soy de marcadores de su answaer y tan pronto como puedo obtener más información acerca de roscado estoy seguro que va a revesit ella! Muchas gracias!
guilfer

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................