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

Python多文件异常跳转:如何让File B抛异常回到File A指定位置

解决方案

问题根源分析

你遇到的核心问题是自定义STOP异常被File B中捕获所有异常的except Exception块拦截后,虽被重新抛出,但可能被with self.media.getSynchronous()的上下文管理器吞噬,或因代码缩进/循环逻辑问题导致异常未正确穿透到File A。

具体解决方法

方法1:精准捕获异常,避免泛用except Exception

修改File B中的异常捕获逻辑,单独处理STOP异常,确保它能无阻碍地向上传递到File A的try-except块:

with self.media.getSynchronous():
    if not reply.isStreaming():
        self.writeTrace("TX: " + self.now() + "	" + GXByteBuffer.hex(data), TraceLevel.VERBOSE)
        self.media.send(data)
    pos = 0
    try:
        while not self.client.getData(rd, reply, notify):
            if notify.data.size != 0:
                if not notify.isMoreData():
                    t = GXDLMSTranslator()
                    xml = t.dataToXml(notify.data)
                    print(xml)
                    notify.clear()
                continue
            if not p.eop:
                p.count = self.client.getFrameSize(rd)
            while not self.media.receive(p):
                pos += 1
                if pos == 4:
                    raise TimeoutException("Failed to receive reply from the device in given time.")
                if pos == 1:
                    self.counter += 1
                    if self.counter >= 2:
                        logging.warning(f"Worker {self.worker_id} | counter is {self.counter}")
                        raise STOP(f"Data send failed, limit reached ({self.counter})")
                logging.info(f"Worker {self.worker_id} | Meter ({self.meternummer}) - Data send failed. Try to resend " + str(pos) + f"/3, times: {self.counter}")
                self.media.send(data, None)
            rd.set(p.reply)
            p.reply = None
    # 单独捕获STOP异常,直接重新抛出(保留完整异常栈)
    except STOP as e:
        self.writeTrace(f"触发终止流程: {str(e)}", TraceLevel.ERROR)
        raise
    # 处理其他类型异常
    except Exception as e:
        self.writeTrace("RX: " + self.now() + "	" + str(rd), TraceLevel.ERROR)
        raise
    self.writeTrace("RX: " + self.now() + "	" + str(rd), TraceLevel.VERBOSE)
    if reply.error != 0:
        raise GXDLMSException(reply.error)

方法2:检查上下文管理器是否吞噬异常

with self.media.getSynchronous()的上下文管理器(__exit__方法)如果返回True,会吞噬所有异常。如果这是第三方库的实现:

  1. 查阅该库文档,确认是否有参数可控制异常处理行为;
  2. 若无法修改上下文管理器,可在with块内捕获STOP异常后,主动退出所有循环,待with块结束后再重新抛出异常。

方法3:用标志位替代异常(更稳妥的流程控制)

如果异常传递始终有问题,可改用标志位主动终止循环,再让File A判断并处理:
在File B的类中添加标志位:

# 类初始化时定义标志位
self.should_abort = False

# 函数内逻辑
with self.media.getSynchronous():
    # ... 其他代码
    pos = 0
    self.should_abort = False
    try:
        while not self.client.getData(rd, reply, notify) and not self.should_abort:
            # ... 其他逻辑
            while not self.media.receive(p) and not self.should_abort:
                pos += 1
                # ...
                if pos == 1:
                    self.counter += 1
                    if self.counter >= 2:
                        logging.warning(f"Worker {self.worker_id} | counter is {self.counter}")
                        self.should_abort = True
                        break  # 退出内层循环
                # ...
            if self.should_abort:
                break  # 退出外层循环
        # ... 后续代码
    except Exception as e:
        self.writeTrace("RX: " + self.now() + "	" + str(rd), TraceLevel.ERROR)
        raise
    # 函数末尾返回标志位
    return self.should_abort

在File A中调用:

try:
    b_obj = BClass()
    abort_flag = b_obj.your_target_function()
    if abort_flag:
        raise STOP("Data send failed, limit reached")
except STOP as e:
    # 处理终止后的逻辑
    print(str(e))

必查:修复代码缩进错误

你提供的代码中with self.media.getSynchronous():后的if not reply.isStreaming()没有缩进,这是Python语法错误,会导致代码运行异常,必须修正缩进,确保with块内的所有代码都正确缩进。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:15:07