【发布时间】:2016-02-11 14:58:03
【问题描述】:
在 Tornado 协程中等待来自 ThreadPoolExecutor 的 concurrent.futures.Future 有时会为我挂起:
def slowinc(x):
time.sleep(0.1)
return x + 1
yield tp_executor.submit(slowinc, 1) # sometimes hangs
当我添加超时时,它可能会在超时期间挂起,但似乎在该时间之后实际上返回了正确的结果。
yield gen.with_timeout(timedelta(seconds=5),
executor.submit(...)) # hangs for 5sec, then works
这只发生在较大的测试套件的上下文中,其中会发生许多不愉快的事情(子进程在中途终止)。这个错误几乎肯定与这个令人不快的环境有关,而不是严格意义上的 Tornado 的错。但是,我相信我已经尽可能地隔离了这些不愉快的事情。
因此,对于细微的错误和缺乏简单的可重复示例,我深表歉意。我希望失败超时的奇怪行为实际上导致成功有助于隔离我的问题。
临时解决方案
到目前为止,我的解决方案如下:
while not future.done():
try:
yield gen.with_timeout(timedelta(seconds=1), future)
except gen.TimeoutError:
pass
result = future.result()
这解决了我的直接问题,除了偶尔的一秒钟延迟之外,它完全可以使用。尽管如此,我仍然对这种行为感到困惑,并且很好奇我正在做什么奇怪的事情来触发这种行为。
更新
上面的超时解决方案适用于 Tornado 4.2 和 4.3 下的 Python 3.4,但@ben-darnell 的答案中的timeout 解决方案和PeriodicCallback 解决方案都不能解决 Python 2.7 Tornado 4.2 或 4.3 下的这个问题.
【问题讨论】:
-
执行者是
ThreadPoolExecutor还是ProcessPoolExecutor? -
编辑声明这是来自 ThreadPoolExecutor。
-
在 python 2.7 中出现同样的问题。 @gen.coroutine 在某个时间后抛出 WebSocketClosedError