等待Tornado协程中的concurrent.futures.Future
的{{1}}有时会对我不利:
ThreadPoolExecutor
当我添加超时时,它可能会在超时期间挂起,但在此之后似乎实际上会返回正确的结果。
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 4.2和4.3下的Python 3.4,但@ ben-darnell的回答中提到的while not future.done():
try:
yield gen.with_timeout(timedelta(seconds=1), future)
except gen.TimeoutError:
pass
result = future.result()
解决方案和timeout
解决方案都没有解决Python 2.7下的这个问题龙卷风4.2或4.3。
答案 0 :(得分:1)
我没有完整的解决方案,但我认为我可以提供更简单的解决方法:启动一个在短时间内无效的后台PeriodicCallback
:PeriodicCallback(lambda: None, 500).start()
。这将确保IOLoop定期唤醒而不会侵入您的所有yield executor.submit()
来电。
症状表明问题出在" waker" add_callback
的行为:https://github.com/tornadoweb/tornado/blob/d9c5bc8fb6530a03ebbb6da667e26685b8eee0ea/tornado/ioloop.py#L929-L944
此代码在Tornado 4.3(https://github.com/tornadoweb/tornado/pull/1511/files)中已更改。如果您在4.3上,请查看问题是否仍然存在于4.2中。在你的"令人不快的"环境导致thread.get_ident()
的行为与龙卷风期望的不同?
据报道,waker" pipe"在Windows上:https://github.com/tornadoweb/tornado/pull/1364