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,会吞噬所有异常。如果这是第三方库的实现:
- 查阅该库文档,确认是否有参数可控制异常处理行为;
- 若无法修改上下文管理器,可在
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
相关产品推荐
相关产品推荐

