You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Twisted中捕获网络断开时的DNSLookupError异常?

处理Twisted中DNSLookupError的实用方案

我之前刚好踩过这个坑,Twisted的异步错误处理机制需要明确绑定errback,不然未处理的Deferred错误就会疯狂污染日志。下面给你几个具体的解决办法:

1. 给单个请求的Deferred添加专属Errback

这是最直接的方式,针对每个发起的请求,绑定一个错误回调函数,专门捕获并处理DNSLookupError:

from twisted.web.client import Agent
from twisted.internet import reactor
from twisted.internet.error import DNSLookupError
from twisted.python import log

def handle_success(response):
    # 正常处理响应的逻辑
    print(f"收到响应,状态码:{response.code}")
    return response

def handle_request_error(failure):
    # 精准捕获DNSLookupError
    if failure.check(DNSLookupError):
        log.msg("⚠️ DNS解析失败,大概率是网络断开了", level=log.Level.info)
        # 这里可以加自定义逻辑,比如延迟重试、标记任务状态等
        return None  # 返回None表示错误已被处理,不会继续向上传播
    # 其他类型的错误,可以选择重新抛出或者另行处理
    log.err(failure, "❌ 遇到未预期的请求错误")
    return failure

# 初始化Agent并发起请求
agent = Agent(reactor)
request_deferred = agent.request(b'GET', b'https://api.yourdomain.com/endpoint')

# 绑定成功回调和错误回调
request_deferred.addCallback(handle_success)
request_deferred.addErrback(handle_request_error)

reactor.run()

2. 封装通用错误处理函数(批量请求场景)

如果你的脚本需要发起大量请求,没必要给每个请求都写重复的errback,可以封装一个通用的错误处理器:

def universal_error_handler(failure):
    error_types = {
        DNSLookupError: "网络断开导致DNS解析失败",
        # 还可以添加其他需要捕获的异常,比如ConnectionRefusedError等
    }
    for err_type, msg in error_types.items():
        if failure.check(err_type):
            log.msg(f"⚠️ {msg}", level=log.Level.info)
            return None
    # 未匹配到的错误,记录完整回溯但不污染日志
    log.err(failure, "❌ 未处理的请求异常")
    return failure

# 每个请求都可以复用这个处理器
d1 = agent.request(b'GET', b'https://api.example.com/1')
d1.addCallback(handle_success)
d1.addErrback(universal_error_handler)

d2 = agent.request(b'GET', b'https://api.example.com/2')
d2.addCallback(handle_success)
d2.addErrback(universal_error_handler)

3. 全局异常捕获(谨慎使用)

如果想统一处理所有未被捕获的Deferred错误,可以给Twisted的日志系统添加自定义观察者,过滤掉DNSLookupError的冗余回溯:

from twisted.python.log import textFromEventDict

def custom_log_observer(event):
    text = textFromEventDict(event)
    # 过滤掉DNSLookupError的未处理错误日志
    if "Unhandled error in Deferred:" in text and "DNSLookupError" in text:
        log.msg("⚠️ 全局捕获:DNS解析失败(网络可能断开)", level=log.Level.info)
        return
    # 其他日志正常输出
    print(text)

# 替换默认的日志观察者
log.startLoggingWithObserver(custom_log_observer, setStdout=False)

关键原理说明

Twisted的Deferred对象在异步操作失败时,会生成一个Failure对象。如果没有绑定errback来处理这个Failure,它最终会被抛到全局日志系统,产生你看到的Unhandled error in Deferred:信息。只要给每个Deferred都绑定对应的errback,就能把错误处理逻辑掌握在自己手里,避免日志污染。

内容的提问来源于stack exchange,提问作者Yuri Lifanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:16:36