2013-10-06 22 views
1

我有一个问题,在龙卷风默默传递异常,而在情况下使用期货,当我没有明确的未来的协同程序(yield some_future_obj),如无限循环协同程序等待结果:默默传递异常与未来的对象

@gen.coroutine 
def base_func(): 

    @gen.coroutine 
    def tail_something(): 
     raise 
     while True: 
      yield some_other_coroutine 

    base_func() 

我也注意到这个话题已经被讨论过了:参考herehere。 问题是,如果我们不等待明确的未来完成,future.result()永远不会被调用,并且异常将永远不会被引发。但是tornado.concurrent承诺使用concurrent.futures包。

现在,我只是将ioloop.add_future挂在当前循环上,然后执行log.exception(future.result())。但我不喜欢这种方法,因为它有点嘈杂(生产代码中的冗余行)。

请提出您的想法或者可能是一个真正的答案。

回答

4

期货“隐藏”例外的原因是,您必须决定,其中您希望显示异常。如果你想能够处理你的代码中的异常,你必须在某个地方访问它的结果(这在Tornado协同程序中意味着产生它)。如果你只是想记录异常,你可以问IOLoop来为你做它:

IOLoop.instance().add_future(fut, lambda fut: fut.result()) 

注意,我打电话()的结果,而不是记录它的价值。这确保我们不会在没有错误时记录任何内容,并且异常(带回溯)由IOLoop的正常未处理异常机制记录。

+0

谢谢,非常好的答案,本。我忘了我们可以简单地订阅任何未来的结果。 –

+0

如果协程是回调,那么应该在每次准备处理某些数据时调用它。例如,RabbitMq异步使用者使用来自指定队列的消息,并将所有消息接收到一些回调方法,例如“on_message”,后者又必须调用一些异步代码并等待其回复。在这种情况下''on_message''是协程,但没办法处理那里的异常。 –

+1

在这种情况下,您可能需要在RabbitMq和真正的协程之间插入一个非协程平衡,以便获得协程的未来结果并将其添加到IOLoop。 –