[分享技术]如何使用Python制作一个多线程下载系统(丝滑回显)~

[分享技术]如何使用Python制作一个多线程下载系统(丝滑回显)~

lenmei233
5天前发布

多线程下载的原理是通过将一个文件分成多个部分,每个部分由一个线程同时下载,从而提高下载速度,那么我们如何使用Python去制作一个呢。
以下是详细的步骤和原理:

demo

1. 获取文件大小

首先,通过向服务器发送HEAD请求获取文件的总大小。这一步是为了确定文件的总字节数,以便后续的分块下载。

response = requests.head(url)
file_size = int(response.headers.get('content-length', 0))

2. 创建空文件

在本地创建一个与文件大小相同的空文件。这一步是为了后续的写入操作做准备。

with open(filename, "wb") as f:
    f.write(b'\0' * file_size)

3. 分块下载

将文件分成多个部分,每个部分由一个线程下载。通过Range请求头指定每个线程下载的字节范围。

part_size = file_size // num_threads
start = part_size * i
end = start + part_size - 1 if i < num_threads - 1 else file_size - 1
headers = {'Range': f'bytes={start}-{end}'}
response = requests.get(url, headers=headers, stream=True)

4. 写入文件

每个线程下载其负责的部分,并将下载的内容写入到对应的文件位置。

with open(filename, "r+b") as f:
    f.seek(start)
    for chunk in response.iter_content(chunk_size=1024):
        if chunk:
            f.write(chunk)

5. 进度更新

在下载过程中,实时更新下载进度。通过一个独立的线程每半秒从队列中获取下载的字节数,并计算当前的下载进度和速度。

def update_progress(progress_queue, total_size, start_time):
    while True:
        try:
            while not progress_queue.empty():
                progress_queue.get_nowait()
        except:
            pass

        with lock:
            downloaded = total_downloaded

        percent = (downloaded / total_size) * 100
        elapsed_time = time.time() - start_time
        if elapsed_time > 0:
            speed = downloaded / elapsed_time / 1024  # KB/s
        else:
            speed = 0

        print(f"\rDownloaded: {downloaded}/{total_size} bytes ({percent:.2f}%) - Speed: {speed:.2f} KB/s", end="")

        if downloaded >= total_size:
            break

        time.sleep(0.5) #等待0.5秒回显提供视觉效果

6. 线程安全

使用threading.Lock确保在更新total_downloaded时的线程安全,避免多个线程同时修改导致的数据不一致。

with lock:
    total_downloaded += len(chunk)

总结

多线程下载通过将文件分成多个部分并同时下载,显著提高了下载速度。通过实时更新进度,用户可以直观地看到下载的进度和速度。线程安全机制确保了数据的一致性,避免了潜在的竞态条件。

谢谢你看到最后,想要demo可以直接在下面下载哦~

© 版权声明
THE END
喜欢就支持一下吧
点赞 0 分享 赞赏
评论 共1条
取消
  1. 头像
    lenmei233 作者
    Windows 10 · Google Chrome

    回复可见

    回复
易航博客
SSL