Aqui está uma versão que vai baixar o arquivo em um bytearray
em uma thread separada.
Como mencionado em outras respostas e comentários, há outros alternativs que são desenvolvidos com operações assíncronas em mente, então não leia muito para a decisão de ir com threading
, é apenas para demonstrar o conceito (e, por conveniência, uma vez que ele vem com python).
No código abaixo, se o tamanho do arquivo é conhecido, cada .
corresponderá a 1%. Como um bônus, o download e o número total de bytes que serão impressos no início da linha, como (1234 B / 1234567 B)
. Se tamanho não for conhecido, a solução alternativa é ter cada .
representam um bloco.
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()
Tenha em mente que deixei de fora o bloqueio para proteger contra o acesso simultâneo stdout
para reduzir o ruído. Eu também deixou de fora a escrever a bytarray
para arquivo no final (ou a escrita de blocos de arquivo como eles são recebidos se o arquivo for grande), mas tenha em mente que você pode querer usar um bloqueio para que bem se você ler e/ou escrever para o mesmo ficheiro em qualquer outra parte do seu script.