Come stampare "puntini" (o altro tipo di feedback) durante la scrittura di un file in python?

0

Domanda

Sto cercando di stampare un riscontro per l'utente del terminale mentre la mia applicazione donwloads un file dal web e scrivere il disco rigido, ma non sono riuscito a trovare come fare a leggere la documentazione o googling di esso.

Questo è il mio codice:

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

Io mi aspettavo di capire come fare qualcosa di simile a questo:

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

Io sono davvero strugling anche per iniziare, perché nessuno dei metodi restituisce una "promessa" (come in JS).

Qualsiasi aiuto sarebbe molto apprezzato! Grazie!

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

Migliore risposta

3

requests.get per impostazione predefinita scarica l'interezza delle risorse richieste, prima che diventi di nuovo voi. Tuttavia, è un argomento opzionale stream, che consente di richiamare .iter_content o .iter_lines sul Response oggetto. Questo ti permette di prendere azione ogni N byte (o come ogni pezzo di dati arriva), o in ogni linea, rispettivamente. Qualcosa di simile a questo:

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)

Questo ancora blocchi, in modo che nessun altro lo farà accadere. Se si desidera più di JavaScript stile, per Grismar commento, si dovrebbe eseguire in Python async loop. In questo caso, ti suggerisco di usare aiohttp piuttosto che requests, in quanto è creato con async stile in mente.

2021-11-24 06:52:04

Grazie mille per la tua risposta! E ' stato molto veloce!!! haha ho fatto interpretare e il concetto e il suo bene sapere che ci sono async funzioni in python. Per qualche ragione, quando ho provato a aply codice, stampato solo il file dopo la richiesta di avere finito. Probabilmente mi manca qualcosa...
guilfer
1

Ecco una versione che si scarica il file in un bytearray in un thread separato.

Come già detto in altre risposte e commenti, ci sono altri alternativs che sono sviluppati con operazioni asincrone in mente, in modo da non leggere troppo in la decisione di andare con threading, è solo per dimostrare che il concetto (e a causa della convenienza, in quanto si tratta con python).

Nel codice qui sotto, se la dimensione del file è noto, ogni . corrisponde all ' 1%. Come bonus, scaricato e numero totale di byte verrà stampato all'inizio della linea (1234 B / 1234567 B). Se la dimensione non è noto, la soluzione di ripiego è quello di avere ogni . rappresentano un pezzo.

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()

Non tenere a mente che ho lasciato fuori il blocco per la protezione contro l'accesso simultaneo a stdout per ridurre il rumore. Ho anche lasciato fuori la scrittura bytarray per file alla fine (o la scrittura dei pezzi di file ricevuto, se il file è di grandi dimensioni), ma tenete a mente che si desidera utilizzare un lucchetto per questo e se si di leggere e/o scrivere lo stesso file in qualsiasi altra parte del vostro script.

2021-11-24 05:57:53

Che è incredibile! Credo di aver capito il concetto, ma io sono abbastanza nuovo per python e ho deciso di andare il modo più semplice haha io sono bookmarking tuo answaer e non appena mi saperne di più circa la filettatura ho certo intenzione di revesit it! Grazie mille!
guilfer

In altre lingue

Questa pagina è in altre lingue

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