2017-03-28 1467 views
4

我试图通过多个进程使用tqdm。行为并不如预期。我认为重点在于pbar的值不会通过这些进程更新。那么如何处理这个问题呢?我也尝试用Value手动更新pbar.n,但仍然失败。看起来tqdm不支持更新值并手动呈现。如何在python中通过多进程使用tqdm?

def test(lock, pbar): 
    for i in range(10000): 
     sleep(0.1) 
     lock.acquire() 
     pbar.update() 
     lock.release() 

pbar = tqdm(total = 10000) 
lock = Lock() 
for i in range(5): 
    Process(target = test, args = (lock, pbar)) 

回答

4

一般来说,每个进程都有自己的数据,与其他进程无关。 产生一个新进程(在Unix上调用os.fork)创建当前进程的副本。每个进程都会获取其全部全局值的副本(如 pbar)。每个进程的全局变量可以与其他进程中的变量 共享相同的名称,但每个进程都可以保存一个独立的值。

在你的情况下,它看起来像你想只是一个pbar存在,并 update所有呼叫应更新一个pbar。因此,在只有一个进程创建pbar, 并使用Queue将信号发送到该进程更新pbar

import multiprocessing as mp 

SENTINEL = 1 

def test(q): 
    for i in range(10000): 
     sleep(0.1) 
     q.put(SENTINEL) 

def listener(q): 
    pbar = tqdm(total = 10000) 
    for item in iter(q.get, None): 
     pbar.update() 

if __name__ == '__main__': 
    q = mp.Queue() 
    proc = mp.Process(target=listener, args=(q,)) 
    proc.start() 
    workers = [mp.Process(target=test, args=(q,)) for i in range(5)] 
    for worker in workers: 
     worker.start() 
    for worker in workers: 
     worker.join() 
    q.put(None) 
    proc.join() 
+0

它运作良好,除了块永远在'proc.join()'。我认为可以通过在'proc.join()'之前添加'q.put(None)'来完成侦听器进程。非常感谢。 – Sraw

+0

@Sraw:哎呀,你说得很对。感谢您的更正。 – unutbu

相关问题