You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MultiProcessing多文件下载时进度条重复打印问题求助

问题解决:多进程下载时进度条重复打印的修复

问题原因

每个子进程独立创建并渲染alive_bar,多个进程同时向终端输出刷新指令,终端无法处理多个进度条的并行更新,导致进度条重复打印、显示混乱。

解决方案

让主进程统一管理进度显示,子进程仅负责下载任务,并通过进程间队列(multiprocessing.Queue)向主进程上报下载进度,由主进程单独更新进度条。

修改后的完整代码

from multiprocessing import Process, Queue
from alive_progress import alive_bar
import requests
import time
import os

def download(url, queue):
    curr_dir = os.getcwd()
    # 获取文件真实地址和大小
    try:
        x = requests.head(url, allow_redirects=True)
        file_size = int(x.headers['content-length']) // 1024  # 转为KB
        chunk_size = 1024
    except Exception as e:
        print(f"获取文件信息失败: {e}")
        queue.put(('error', url))
        return

    file_name = f"{curr_dir}\\{int(time.time())}.mp4"
    response = requests.get(url, stream=True)
    
    downloaded = 0
    with open(file_name, 'wb') as f:
        for chunk in response.iter_content(chunk_size=chunk_size):
            if chunk:
                f.write(chunk)
                downloaded += 1
                queue.put(('progress', 1))  # 每下载1KB发送一次进度
    
    queue.put(('done', url))

if __name__ == '__main__':
    # 示例下载链接(替换为你的实际链接)
    links = [
        "https://example.com/file1.mp4",
        "https://example.com/file2.mp4"
    ]
    num_processes = 2
    processes = []
    progress_queue = Queue()
    
    # 计算总文件大小(用于总进度条)
    total_size = 0
    for url in links:
        try:
            x = requests.head(url, allow_redirects=True)
            total_size += int(x.headers['content-length']) // 1024
        except:
            print(f"无法获取{url}的文件大小")
    
    # 启动子进程
    for url in links[:num_processes]:
        p = Process(target=download, args=(url, progress_queue))
        processes.append(p)
        p.start()
    
    # 主进程处理进度并更新进度条
    completed = 0
    with alive_bar(total_size, bar='classic2', spinner='classic') as bar:
        while completed < num_processes:
            msg_type, data = progress_queue.get()
            if msg_type == 'progress':
                bar(data)
            elif msg_type == 'done':
                completed += 1
                print(f"\n{data} 下载完成!")
            elif msg_type == 'error':
                completed += 1
                print(f"\n{data} 下载失败!")
    
    # 等待所有进程结束
    for p in processes:
        p.join()

关键修改点

  • 使用multiprocessing.Queue实现主进程和子进程的进度通信,避免子进程直接输出到终端
  • 主进程单独创建并控制alive_bar,所有进度更新由主进程统一处理
  • 修复原代码中for i in num_processess的语法错误(改为遍历链接列表)
  • 增加异常处理,避免单个文件下载失败导致整个程序崩溃

内容的提问来源于stack exchange,提问作者Syed Abdullah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:35:33