Python 以静默方式传递未来对象的异常

Python 以静默方式传递未来对象的异常,python,asynchronous,tornado,nonblocking,coroutine,Python,Asynchronous,Tornado,Nonblocking,Coroutine,我在tornado中使用futures时遇到了一个问题,在这种情况下,当我没有明确等待来自未来协同路由的结果(产生一些未来的obj),例如无限循环协同路由: @gen.coroutine def base_func(): @gen.coroutine def tail_something(): raise while True: yield some_other_coroutine base_func() 我也注

我在tornado中使用futures时遇到了一个问题,在这种情况下,当我没有明确等待来自未来协同路由的结果(
产生一些未来的obj
),例如无限循环协同路由:

@gen.coroutine
def base_func():

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

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

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

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

期货“隐藏”异常的原因是您必须决定要在哪里显示异常。如果您希望能够处理代码中的异常,那么必须在某个地方访问它的结果(在Tornado协同程序中,这意味着产生它)。如果您只想记录异常,可以让IOLoop为您执行以下操作:

IOLoop.instance().add_future(fut, lambda fut: fut.result())
注意,我只是调用result()而不是记录它的值。这确保了我们在没有错误时不会记录任何内容,并且异常(带有回溯)由IOLoop的正常未处理异常机制记录。

期货“隐藏”异常的原因是您必须决定异常显示的位置。如果您希望能够处理代码中的异常,那么必须在某个地方访问它的结果(在Tornado协同程序中,这意味着产生它)。如果您只想记录异常,可以让IOLoop为您执行以下操作:

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

注意,我只是调用result()而不是记录它的值。这确保了我们在没有错误的情况下不会记录任何内容,并且异常(带有回溯)由IOLoop的正常未处理异常机制记录。

谢谢,回答得很好,Ben。我忘了,我们可以简单地订阅任何未来的结果。如果协程是回调,那么当某些数据准备好处理时,应该每次调用它。例如,RabbitMq异步使用者使用指定队列中的消息,并将所有消息接收到某个回调方法,如\u message上的
,该回调方法反过来必须调用某些异步代码并等待其答复。在这种情况下,消息上的
是协同路由,但无法处理异常。在这种情况下,您可能需要在RabbitMq和实际协同路由之间插入一个非协同路由垫片,这样您就可以获得协同路由的未来结果并将其添加到IOLoop中。谢谢,回答得很好,Ben。我忘了,我们可以简单地订阅任何未来的结果。如果协程是回调,那么当某些数据准备好处理时,应该每次调用它。例如,RabbitMq异步使用者使用指定队列中的消息,并将所有消息接收到某个回调方法,如\u message
上的
,该回调方法反过来必须调用某些异步代码并等待其答复。在这种情况下,消息上的
是协同路由,但无法处理异常。在这种情况下,您可能需要在RabbitMq和实际协同路由之间插入一个非协同路由垫片,以便获得协同路由的未来结果并将其添加到IOLoop中。