使用tqdm处理不是循环的进程是否可行?

11
我正在编写一个程序,其中一项操作需要几秒钟(加载大文件)。幸运的是,它总是需要相同的时间。所以,为了用户的方便,我想制作一个进度条。然而,tqdm似乎是为循环设计的。假设sleep(10)是需要消耗时间的过程。我该怎么办呢?
我想为一个非循环的长过程制作一个进度条。
from time import time, sleep
from tqdm import tqdm

for i in tqdm([1]):
    sleep(10)

这段代码存在的问题是进度条会一直停留在零,然后在过程结束时跳到100%。我想要一个进度条,在10秒的过程中能够持续不断地变化。

但是你已经有一个循环了。我看不出问题,你能再详细解释一下吗? - adam
使用tqdm,像这样只有一个操作的循环将在零处等待,然后在进程结束时跳转到100%。我想要一个进度条,在10秒钟内逐渐发展。 - Nicolas Gervais
1
我认为tqdm适用于长循环,而不是需要很长时间的短循环。这是因为tqdm根据一个周期完成的平均时间来估计ETA,所以它并不是那么有用。 - adam
有一种方法可以手动创建和更新进度条,但是您必须直接在进程内配置更新,我不知道进度估计的准确性如何。 - A Co
4个回答

9
手动设置tqdm的进度值:
#Manually set p_bar
p_bar = tqdm(range(10))
p_bar.update(5)
p_bar.refresh()
time.sleep(1)
#another way to do it
p_bar.n = 7
p_bar.refresh()

4
你可以定义块大小。持续10秒的进度条假定你已经知道加载文件需要多少时间... 试试这个。
from tqdm import tqdm_notebook as tqdm

chunk_size = 1000
total_chunks=nrows/chunk_size

chunks = pd.read_sql_query(query, connection, index_col='index_name',chunksize= chunk_size)
raw_train_data=pd.DataFrame()

with tqdm(total=total_chunks) as pbar:

    for chunk in chunks:
        raw_train_data = pd.concat([raw_train_data, chunk])
        pbar.update(1)

这假设你可以将进程分成块。我猜这不是OP的进程情况。 - Joseph Budin

2
for _ in tqdm(range(10),desc="waiting..."):
    time.sleep(1)

3
请勿仅以代码形式回答问题,同时提供说明您的代码是如何解决问题的。附上解释通常更有益且质量更高,并更可能获得赞同。 - Boken

2

您可以使用线程来加载文件,并循环遍历tqdm(range(10)),直到文件加载完成,如下所示:

import logging
import threading
import time
from tqdm import tqdm


def thread_function(name):
    logging.info("Thread %s: starting", name)
    logging.info("Main    : file loading...")
    time.sleep(5)
    logging.info("Thread %s: finishing", name)


if __name__ == "__main__":
    logging.basicConfig(format="%(asctime)s: %(message)s", level=logging.INFO,
                        datefmt="%H:%M:%S")

    x = threading.Thread(target=thread_function, args=(1,))
    x.start()
    for i in tqdm(range(10)):
        if not x.is_alive():
            break
        time.sleep(1)
    x.join()
    logging.info("Main    : end.")

太棒了。你能指导我如何控制它的宽度吗?它超出了一行。 - Nicolas Gervais
你只需要删除任何 logging.info 或 print() 调用即可。 - DavidBu
这里的“问题”是range(n)中的n必须足够大以容纳thread_function的运行时间,以便显示进度。但是,然后,进度条总会提前停止,永远无法达到100%。如果反过来,进度条将达到100%,但随后只会坐在那里不再显示进度。两者都不是很好,但我想既然我们不知道(按设计)运行函数需要多长时间,那么就没有办法绕过它。 - NichtJens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接