我正在嘗試在終端中為用戶列印可見的反饋,而我的應用程式從 Web 下載檔案并將其寫入硬碟驅動器,但我無法通過閱讀檔案或谷歌搜索找到如何執行此操作。
這是我的代碼:
res = requests.get(url_to_file)
with open("./downloads/%s" % (file_name), 'wb') as f:
f.write(res.content)
我期待弄清楚如何制作這樣的東西:
Downloading file ........
# it keeps going ultil the download is finished and the file writen
Done!
我什至很難開始,因為沒有一個方法回傳“承諾”(就像在 JS 中一樣)。
任何幫助將不勝感激!謝謝!
uj5u.com熱心網友回復:
requests.get默認情況下,在回傳給您之前下載請求的全部資源。但是,它有一個可選引數stream,它允許您在物件上呼叫.iter_content或。這允許您每 N 個位元組(或在每個資料塊到達時)或在每一行分別采取行動。像這樣的東西:.iter_linesResponse
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)
但這仍然會阻塞,因此不會發生任何其他事情。如果你想要更多的 JavaScript 風格,根據 Grismar 的評論,你應該在 Python 的異步回圈下運行。在這種情況下,我建議使用aiohttp而不是requests,因為它是用異步風格創建的。
uj5u.com熱心網友回復:
這是一個將檔案下載到bytearray單獨執行緒中的版本。
正如其他答案和評論中所提到的,還有其他替代方案是在考慮異步操作的情況下開發的,所以不要過多地了解要使用的決定threading,這只是為了演示這個概念(并且因為方便,因為它來了與蟒蛇)。
在下面的代碼中,如果檔案的大小是已知的,每個.將對應 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以減少噪音。我還沒有在最后寫入bytarrayto 檔案(或者如果檔案很大,則在收到塊時將塊寫入檔案),但請記住,如果您閱讀,您可能也想為此使用鎖和/或在腳本的任何其他部分寫入同一個檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/365456.html
