扭曲:如果回调发生错误,则不会出现异常跟踪
考虑以下代码:
df = defer.Deferred()
def hah(_): raise ValueError("4")
df.addCallback(hah)
df.callback(hah)
当它运行时,该异常就会被吃掉。它去哪儿了?我怎样才能让它显示出来?执行 defer.setDebugging(True) 没有效果。
我问这个问题是因为其他时候,我会收到一个打印输出,上面写着“延迟中未处理的错误:”。在这种情况下我怎样才能做到这一点?我看到,如果我向 df 添加 errback,则会调用 errback,但会出现异常,但我只想打印错误,不执行其他任何操作,而且我不想手动添加我创建的每个延迟的处理程序。
Consider the following code:
df = defer.Deferred()
def hah(_): raise ValueError("4")
df.addCallback(hah)
df.callback(hah)
When it runs, that exception just gets eaten. Where did it go? How can I get it to be displayed? Doing defer.setDebugging(True)
has no effect.
I ask this because other times, I get a printout saying "Unhandled error in Deferred:". How do I get that to happen in this case? I see that if I add an errback to df
then the errback gets called with the exception, but all I want to do is print the error and do nothing else, and I don't want to manually add that handler to every deferred I create.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
例外情况仍然处于 Deferred 状态。此时有两种可能的结果:
因为 errback 可以随时添加到 Deferred(即上面的第一点),所以 Deferred 不会立即对未处理的错误执行任何操作。他们不知道错误是否真的未处理,或者只是到目前为止尚未处理。只有当 Deferred 被垃圾收集时,才能确定没有其他人会处理该异常,因此此时它会被记录下来。
一般来说,您需要确保 Deferreds 上有 errbacks,正是因为有时很难预测 Deferreds 何时会被垃圾收集。这可能需要很长时间,这意味着如果您没有附加自己的错误返回,那么您可能需要很长时间才能了解异常。
这不一定是一个可怕的负担。从另一个 Deferred (b) 的回调返回的任何 Deferred (a)(即,当发生链接时)都会将其错误传递给 b。因此,(a) 不需要额外的错误返回来进行日志记录和报告,只有 (b) 需要。如果您有一项复杂且涉及许多异步操作的逻辑任务,则几乎总是这样,参与这些操作的所有 Deferred 都应将其结果(成功或失败)传递给代表该逻辑操作的一个主 Deferred。您通常只需要对该 Deferred 进行特殊的错误处理行为,这将允许您处理来自任何其他涉及的 Deferred 的错误。
The exception is still sitting in the Deferred. There are two possible outcomes at this point:
df
, or return from the function, or lose the reference in any other way). This triggers the ''Unhandled error in Deferred'' code.Because an errback can be added to a Deferred at any time (ie, the first point above), Deferreds don't do anything with otherwise unhandled errors right away. They don't know if the error is really unhandled, or just unhandled so far. It's only when the Deferred is garbage collected that it can be sure no one else is going to handle the exception, so that's when it gets logged.
In general, you want to be sure you have errbacks on Deferreds, precisely because it's sometimes hard to predict when a Deferred will get garbage collected. It might be a long time, which means it might be a long time before you learn about the exception if you don't have your own errback attached.
This doesn't have to be a terrible burden. Any Deferred (a) which is returned from a callback on another Deferred (b) (ie, when chaining happens) will pass its errors along to b. So (a) doesn't need extra errbacks on it for logging and reporting, only (b) does. If you have a single logical task which is complicated and involves many asynchronous operations, it's almost always the case that all of the Deferreds involved in those operations should channel their results (success or failure) to one main Deferred that represents the logical operation. You often only need special error handling behavior on that one Deferred, and that will let you handle errors from any of the other Deferreds involved.