11

我正在尝试tqdm通过多进程使用。并且行为不如预期。我认为关键是 的值pbar不会通过流程更新。那么如何处理这个问题呢?我也尝试使用手动Value更新pbar.n,但仍然失败。它似乎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

1 回答 1

13

通常,每个进程都有自己的数据,独立于其他所有进程。生成一个新进程(os.fork在 Unix 上调用)会创建当前进程的副本。每个进程都获得自己的所有全局值(例如 pbar)的副本。每个进程的全局变量可能与其他进程中的变量共享相同的名称,但每个变量都可以保存一个独立的值。

在您的情况下,您似乎只想要一个pbar存在,并且所有调用都 update应该更新那个pbar. 因此pbar,仅在一个进程中创建,并使用 aQueue向该进程发送信号以进行更新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()
于 2017-03-28T08:35:13.557 回答