Python python 多线程中使用 tqdm 进度条问题

大瓶子 · 2022年10月17日 · 最后由 网络山顶洞人 回复于 2022年10月25日 · 6915 次阅读
from tqdm import tqdm
from time import sleep
from threading import Thread

def jindu():
    for i in tqdm(range(11)):
        sleep(0.1)

tasks = [1,2]
threads = []
for task in tasks:
    t = Thread(target=jindu)
    t.start()
    threads.append(t)
for t in threads:
    t.join()

如果 tasks = [1],单线程执行,进度条显示正常,

tasks = [1,2] 多线程执行就这样的,应该采用什么方法,让一个进度条对应一个线程,不会一直刷新打印新的进度跳

最佳回复

在终端里面是正常的 (windows 系统没试), 默认有提供锁, 实例初始化时会将显示位置 position(指定或自动获取) 记录到全局_instances 里,

锁可以参考 TqdmDefaultWriteLock 类的注释:
Provide a default write lock for thread and multiprocessing safety.
Works only on platforms supporting fork (so Windows is excluded).
You must initialise a tqdm or TqdmDefaultWriteLock instance
before forking in order for the write lock to work.
On Windows, you need to supply the lock from the parent to the children as
an argument to joblib or the parallelism lib you use.

成功获取锁之后会先执行 moveto 方法, 根据 position 将光标移动到相应的位置, 再写 msg, 这段逻辑可以参考 display 方法和 moveto 方法

共收到 9 条回复 时间 点赞
1楼 已删除
2楼 已删除

楼上的是可行的。另外 tqdm 只是适合控制台。如果要做平台的话,有兴趣可以回复我的这条评论。

确实要这样的效果

为什么传参不是 args=(task,),直接在方法名后面 jindu(task)。而且用你的代码运行好像不是多线程运行方式,是一个线程完成之后才运行的下一个线程

在终端里面是正常的 (windows 系统没试), 默认有提供锁, 实例初始化时会将显示位置 position(指定或自动获取) 记录到全局_instances 里,

锁可以参考 TqdmDefaultWriteLock 类的注释:
Provide a default write lock for thread and multiprocessing safety.
Works only on platforms supporting fork (so Windows is excluded).
You must initialise a tqdm or TqdmDefaultWriteLock instance
before forking in order for the write lock to work.
On Windows, you need to supply the lock from the parent to the children as
an argument to joblib or the parallelism lib you use.

成功获取锁之后会先执行 moveto 方法, 根据 position 将光标移动到相应的位置, 再写 msg, 这段逻辑可以参考 display 方法和 moveto 方法

陈子昂 回复

能力达不到做平台,还在点点点阶段😂 😑

Andy 回复

windows 终端也可以

Andy 回复

太高端了,我看 tqdm 官网介绍,和网上查找锁,没有找到相关信息。目前在 cmd 下运行正常的,在 pycharm 会出现图中的结果。

大瓶子 回复

可以直接看源码 😀

from tqdm import tqdm
from time import sleep
import threading


class myThread(threading.Thread):
    def __init__(self, tasks, thread_for):
        threading.Thread.__init__(self)
        self.thread_for= thread_for
        self.tasks = tasks

    def run(self):
        print(f"开启线程: {self.tasks}")
        threadLock.acquire()
        jindu(self.thread_for)
        threadLock.release()


def jindu(thread_for):
    for i in tqdm(range(thread_for)):
        sleep(0.1)


threadLock = threading.Lock()
tasks = [1, 2]
threads = []
for task in tasks:
    t = myThread(task, 11)
    t.start()
    threads.append(t)
for t in threads:
    t.join()

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册