当 Python 个并发的未来对象完成而不进行轮询时,如何停止主线程?

How does one stop the main thread when a Python concurrent future object finishes, without polling?

我有一个函数在另一个函数运行时显示进度条,使用 concurrent.futures.ThreadPoolExecutor

def run_with_loading(function, args=[], kwargs={}, phrase="Loading...", bar_length=5):
    '''
    Run a function while showing a loading bar.
    '''
    with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
        f = executor.submit(function, *args, **kwargs)
        while True:
            for i in range(bar_length):
                if f.done():
                    result = f.result()
                    if f.exception() or not result[0]:
                        c = "✗"
                    else:
                        c = "✔"
                    print(f"[2K\r{phrase} {c}")
                    return result
                sys.stdout.write(
                    f"\r{phrase} {'□' * i}{'■'}{'□' * (bar_length - i - 1)}")
                sys.stdout.flush()
                time.sleep(0.2)

然而,这仍然每 0.2 秒轮询一次以查看生成的函数是否完成。虽然这有效,但我想知道是否有任何更有效的方法来通知 run_with_loading 函数它启动的 function 已经完成。我需要保留是否有异常,代码里写的很清楚,所以可以打印.

您应该使用 concurrent.futures.as_completed 来遍历结果,而不是轮询结果:

with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
    futures = []
    futures.append(executor.submit(function, *args, **kwargs))
    for future in concurrent.futures.as_completed(futures):
        result = f.result()
        if f.exception() or not result[0]:
            c = "✗"
        else:
            c = "✔"
        print(f"[2K\r{phrase} {c}")

您可以在此处找到文档:Futures doc 函数 as_completed 一个遍历所有已完成期货的迭代器,已成功结束。

您需要调整您的 bar_length 方法,但希望这能帮助您对如何等待结果有另一种想法。