#python-3.x #parallel-processing #download #concurrent.futures #tqdm
Вопрос:
Я написал класс с функциями для загрузки файлов с веб-сайта, который требует входа в систему. Я также внедрил панель прогресса в функцию загрузки, чтобы отслеживать ход загрузки с помощью tqdm
. Вот что я написал:
import requests
from requests.auth import HTTPBasicAuth
from pathlib import Path
from tqdm import *
from concurrent.futures import ThreadPoolExecutor, as_completed # for parallel downloads
class DownloadClass:
def __init__(self, url: str, usr: str, pwd: str):
self.__file_url = url
self.__usr = usr
self.__pwd = pwd
self.__req_skel = requests.Session()
def get_file_name(self):
... some stuff
# returns the name of the targeted file using the request lib.
def get_file_size(self):
... some stuff
# returns the file size of the targeted file using request lib
def download_file(self, dl_directory):
_dl_dir = Path(dl_directory)
_target_file = self.get_file_name() '.zip'
_dl_url =self.__file_url
_file_size = self.get_file_size()
with self.__req_skel.get(_dl_url, auth=HTTPBasicAuth(self.__usr, self.__pwd), stream=True) as stream:
if stream.status_code == requests.codes.ok and _dl_dir.exists():
with open(Path(_dl_dir / _target_file), 'wb') as writer:
pbar = tqdm(total=int(_file_size))
for data in stream.iter_content(chunk_size=1024):
writer.write(data)
pbar.update(len(data))
С помощью этого я могу последовательно загружать файлы, например:
urls=[...] # many file-urls which I want to download
user = 'USERNAME'
password = 'PASSWORD'
dl_path = 'PATH_TO_DOWNLOAD_DIRECTORY'
# sequential download
for i in range(len(urls)):
DownloadClass(urls[i], user, password).download_file(dl_path)
Это прекрасно работает, но я хочу загружать файлы параллельно, поэтому я выбрал параллельные фьючерсы:
max_jobs = 3
with ThreadPoolExecutor(max_workers=max_jobs) as ex:
futures = [ex.submit(DownloadClass(file_url, user, password).download_file, dl_path) for file_url in urls]
for future in as_completed(futures):
res = future.result()
По крайней мере, он выполняет 3 задания загрузки, выполняемых параллельно, но вывод терминала-это беспорядок, так как каждый ход загрузки каждого файла выводится на новую строку (вроде как перезаписывается). Я скорее хочу, чтобы в начальной строке был обновлен ход каждой загрузки, как показано здесь. Я нашел несколько примеров, которые просто объединяют общую длину параллельных задач и обновляют ход выполнения всей задачи, но это не то, что я хочу.