V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
rabbbit
V2EX  ›  Python

如何实现多线程下载时,同时显示多个进度条?

  •  
  •   rabbbit · 2017-08-16 23:45:44 +08:00 · 6429 次点击
    这是一个创建于 2662 天前的主题,其中的信息可能已经有所发展或是发生改变。

    希望能分享点相关的代码示例或资料

    开始时想用 tqdm 来着,但总有显示串行等奇怪的 bug.

    相关代码大致如下:

    from tqdm import tqdm
    from multiprocessing.dummy import Pool
    
    def dw(url):
        r = requests.get(url, stream=True)
        size = int(r.headers['Content-Length'])
        progress = tqdm(total=size)
        with open('file', 'wb') as f:
            for chunk in r.iter_content(1024):
                progress.update(len(chunck))
                f.write(chunck)
        progress.close()
    
    
    pool = Pool(5)
    for i in urls:
        pool.apply_async(dw,args=(i))
    pool.close()
    pool.join()
    
    第 1 条附言  ·  2017-08-17 01:05:27 +08:00
    补 5 楼问题 bug 图


    v2ex 总是提示这条回复无法由太新的账号发出,没办法只能挂到 APPEND 里了
    第 2 条附言  ·  2017-08-17 01:19:59 +08:00

    相关部分代码

    position = 0
    def dw(url, path):
        r = requests.get(url, headers=HEADERS, proxies=PROXIES, stream=True)
        global position
        progress = tqdm(
            total=int(r.headers['Content-Length']),
            # unit='B',
            unit_scale=True,
            desc=path,
            # dynamic_ncols=True,
            position=position,
            bar_format='{desc}{percentage}',
        )
        position += 1
        with open(path, 'wb') as f:
            for chunk in r.iter_content(1024):
                progress.update(len(chunk))
                f.write(chunk)
            progress.close()
    
    
    pool = Pool(10)
    for i in urls:
        # i 文件链接
        # path 保存路径
        inf = pool.apply_async(dw, args=(i, path))
    pool.close()
    pool.join()
    
    第 3 条附言  ·  2017-08-17 01:40:27 +08:00
    加了把锁,还是有错,不过比以前少多了.就这样吧,懒得弄了.
    感谢各位的帮助
    mason961125
        1
    mason961125  
       2017-08-17 00:39:44 +08:00
    如果用多线程下载一个文件,那么下载的只是同一个文件的不同区域,分开显示意义不大。
    rabbbit
        2
    rabbbit  
    OP
       2017-08-17 00:43:08 +08:00
    @mason961125 可能我表达有误,同时下载多个文件.
    NoAnyLove
        3
    NoAnyLove  
       2017-08-17 00:49:55 +08:00   ❤️ 1
    不同线程创建自己的 tqdm 实例,传递不同的 position 参数。话说,你们用库都不看文档的吗?
    rabbbit
        4
    rabbbit  
    OP
       2017-08-17 00:52:01 +08:00
    @NoAnyLove 试过了,还是有 bug.
    NoAnyLove
        5
    NoAnyLove  
       2017-08-17 00:52:57 +08:00
    @rabbbit 具体什么样的 bug ?
    SakuraSa
        6
    SakuraSa  
       2017-08-17 00:53:35 +08:00   ❤️ 1
    多行的进度条大约需要 curses 来实现(win 下没有原生的 curses)

    或者你可以使用别人弄好的,例如 blessings
    NoAnyLove
        7
    NoAnyLove  
       2017-08-17 00:59:28 +08:00   ❤️ 1
    @rabbbit 我觉得你需要贴张图说明是什么样的 bug。另外,多个线程可以同时向终端 print,可能会造成混乱。加个锁试试。
    rabbbit
        8
    rabbbit  
    OP
       2017-08-17 01:03:10 +08:00
    @NoAnyLove
    i.imgur. com/90RV9G6

    (没办法只能切开,v2ex 这条回复无法由太新的账号发出)
    链接重复显示,实际上红圈里文件上就下载了一次
    NoAnyLove
        9
    NoAnyLove  
       2017-08-17 08:08:39 +08:00
    NoAnyLove
        10
    NoAnyLove  
       2017-08-17 08:18:05 +08:00
    @rabbbit 上面给的 issue 的链接有我写的示例代码,需要对创建 tqdm、tqdm.update 和 tqdm.close 都要加锁。另外还有个 position 的小技巧,要从 1 开始
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   932 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:51 · PVG 05:51 · LAX 13:51 · JFK 16:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.