代码之家  ›  专栏  ›  技术社区  ›  wim

是否有实际有效的concurrent.futures超时?

  •  4
  • wim  · 技术社区  · 6 年前

    尝试以便宜的价格编写基于进程的超时(同步),如下所示:

    from concurrent.futures import ProcessPoolExecutor
    
    def call_with_timeout(func, *args, timeout=3):
        with ProcessPoolExecutor(max_workers=1) as pool:
            future = pool.submit(func, *args)
            result = future.result(timeout=timeout)
    

    但似乎 timeout 参数传递给 future.result 并不像广告上说的那样有效。

    >>> t0 = time.time()
    ... call_with_timeout(time.sleep, 2, timeout=3)
    ... delta = time.time() - t0
    ... print('wall time:', delta)
    wall time: 2.016767978668213
    

    好啊。

    >>> t0 = time.time()
    ... call_with_timeout(time.sleep, 5, timeout=3)
    ... delta = time.time() - t0
    ... print('wall time:', delta)
    # TimeoutError
    

    不确定 5秒后解锁 ,不是3秒。

    相关问题显示如何使用线程池或 signal . 如何在之后使提交到池的进程超时 n 秒,不使用任何私有的多处理API?硬压井很好,无需要求清洁关闭。

    2 回复  |  直到 6 年前
        1
  •  1
  •   wim    6 年前

    你可能想看看 pebble .

    它的 ProcessPool 旨在解决这个确切的问题:启用超时和取消正在运行的任务,而无需关闭整个池。

    当将来超时或被取消时,工作进程将被实际终止,从而有效地停止执行计划函数。

    超时:

    pool = pebble.ProcessPool(max_workers=1)
    future = pool.schedule(func, args=args, timeout=1)
    try:
        future.result()
    except TimeoutError:
        print("Timeout")
    

    例子:

    def call_with_timeout(func, *args, timeout=3):
        pool = pebble.ProcessPool(max_workers=1)
        with pool:
            future = pool.schedule(func, args=args, timeout=timeout)
            return future.result()
    
        2
  •  1
  •   user2357112    6 年前

    超时正在正常运行。 future.result(timeout=timeout) 在给定超时后停止。 关停 池仍在等待所有挂起的期货完成执行,这会导致意外的延迟。

    您可以通过调用 shutdown(wait=False) 但整个python程序将不会结束,直到所有待定的预购都完成执行:

    def call_with_timeout(func, *args, timeout=3):
        pool = ProcessPoolExecutor(max_workers=1)
        try:
            future = pool.submit(func, *args)
            result = future.result(timeout=timeout)
        finally:
            pool.shutdown(wait=False)
    

    执行器API无法取消已经执行的调用。 future.cancel() 只能取消尚未开始的呼叫。如果您想要突然中止功能,您应该使用除 concurrent.futures.ProcessPoolExecutor .