Вот версия, которая загрузит файл в bytearray
в отдельной теме.
Как упоминалось в других ответах и комментариях, существуют и другие альтернативные варианты, разработанные с учетом асинхронных операций, поэтому не придавайте слишком большого значения решению, с которым следует согласиться threading
, это просто для демонстрации концепции (и из-за удобства, так как она поставляется с python).
В приведенном ниже коде, если известен размер файла, каждый .
будет соответствовать 1%. В качестве бонуса загруженное и общее количество байтов будет напечатано в начале строки следующим образом (1234 B / 1234567 B)
. Если размер неизвестен, резервным решением является наличие каждого .
представляют собой кусок.
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()
Имейте в виду, что я не включил блокировку для защиты от одновременного доступа к stdout
чтобы уменьшить шум. Я также не стал писать bytarray
в файл в конце (или запись фрагментов в файл по мере их получения, если файл большой), но имейте в виду, что для этого также может потребоваться блокировка, если вы читаете и/или записываете в тот же файл в любой другой части вашего сценария.