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.