Comment imprimer des "points" (ou autre type de rétroaction), tandis que l'écriture d'un fichier en python?

0

La question

Je suis en train d'imprimer un visible de la rétroaction de l'utilisateur dans le terminal pendant que mon aplication section téléchargements d'un fichier à partir du web et de l'écrire sur le disque dur, mais je ne pouvais pas trouver comment le faire cette lecture de la documentation ou googler il.

C'est mon code:

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

Je m'attendais à comprendre comment faire quelque chose comme ceci:

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

Je suis vraiment strugling même de commencer, car aucune de ces méthodes renvoie une "promesse" (comme en JS).

Toute aide serait très aprécié! Merci!

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

La meilleure réponse

3

requests.get par défaut, les téléchargements de l'intégralité de la ressource demandée avant que l'on arrive de nouveau à vous. Cependant, il a un argument optionnel streamqui vous permet d'appeler des .iter_content ou .iter_lines sur le Response objet. Cela vous permet de prendre des mesures tous les N octets (ou de chaque bloc de données arrive), ou à chaque ligne, respectivement. Quelque chose comme ceci:

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)

Ce bloque cependant, de sorte que rien d'autre ne se passe. Si vous voulez plus de style JavaScript, par Grismar commentaire, vous devez exécuter sous Python asynchrone en boucle. Dans ce cas, je suggère d'utiliser aiohttp plutôt que de requestscomme il est créé avec async style à l'esprit.

2021-11-24 06:52:04

Merci beaucoup pour votre réponse! Il a été très rapide! haha j'ai fait de comprendre et de concept, il est bon de savoir qu'il y a async fonctions en python. Pour une raison quelconque, quand j'ai essayé de déposer la demande de votre code, Il imprimé uniquement les fichiers après la demande ont fini. Probablement que je suis absent quelque chose...
guilfer
1

Voici une version à télécharger le fichier dans un bytearray dans un thread séparé.

Comme mentionné dans d'autres réponses et commentaires, il y a d'autres alternativs sont développées avec des opérations asynchrones à l'esprit, afin de ne pas lire trop dans la décision d'aller avec threading, c'est juste pour illustrer le concept (et en raison de la commodité, car il est livré avec python).

Dans le code ci-dessous, si la taille du fichier est connu, chaque . correspond à 1%. En bonus, le téléchargement et le nombre total d'octets sera imprimé au début de la ligne comme (1234 B / 1234567 B). Si la taille n'est pas connue, la solution de repli est d'avoir chaque . représenter un morceau.

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

Ne gardez à l'esprit que j'ai quitté la serrure pour protéger contre les accès simultanés à stdout pour réduire le bruit. J'ai aussi laissé de côté l'écriture de l' bytarray de fichier à la fin (ou l'écriture des morceaux de fichier comme ils sont reçus si le fichier est volumineux), mais gardez à l'esprit que vous souhaiterez peut-être utiliser un verrou pour ainsi si vous lire et/ou écrire dans le même fichier dans n'importe quelle autre partie de votre script.

2021-11-24 05:57:53

Qui est géniale! Je crois que je comprends le concept, mais je suis assez nouveau à python et j'ai décidé d'aller le moyen le plus facile haha je suis bookmarking votre answaer et dès que j'en apprendre plus sur le filetage je vais revesit il! Merci beaucoup!
guilfer

Dans d'autres langues

Cette page est dans d'autres langues

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