transitions库中状态转换无效时如何阻止触发器方法执行
问题原因
你遇到的问题根源于重写的_checked_assignment方法的执行顺序:你把自定义业务函数(比如你写的launch、fuel方法)的执行放在了transitions库原生触发器逻辑的前面。而原生触发器的转换合法性校验、MachineError异常抛出逻辑都封装在func参数对应的方法中,所以会出现先执行了你的业务代码、再抛出异常的情况。
解决方案
根据你的业务需求可以选择两种修改方案:
方案1:调整执行顺序(适合自定义逻辑为转换后回调的场景)
如果你的自定义方法不需要在状态转换前执行,只需要在转换成功后运行,直接调换嵌套函数内的执行顺序即可:原生触发器逻辑校验通过、转换成功后才执行业务代码,转换失败抛出异常时不会走到业务逻辑部分。
修改后的_checked_assignment代码如下:
def _checked_assignment(self, model, name, func): if hasattr(model, name): predefined_func = getattr(model, name) def nested_func(*args, **kwargs): # 先执行原生触发器逻辑:不合法直接抛出异常,不会执行后续业务代码 func(*args, **kwargs) # 仅转换成功后执行自定义逻辑 predefined_func(*args, **kwargs) setattr(model, name, nested_func) else: setattr(model, name, func)
方案2:提前校验转换合法性(适合自定义逻辑为转换前回调的场景)
如果你的自定义方法需要在状态转换之前执行,可以通过transitions自动生成的may_<触发器名>方法提前校验转换是否合法,只有校验通过后才执行业务代码和转换逻辑:
def _checked_assignment(self, model, name, func): if hasattr(model, name): predefined_func = getattr(model, name) def nested_func(*args, **kwargs): # 提前校验当前状态下是否可以触发该转换 if not getattr(model, f"may_{name}")(*args, **kwargs): # 不合法直接调用原生触发器抛出标准MachineError异常 func(*args, **kwargs) # 合法则先执行前置自定义逻辑,再执行状态转换 predefined_func(*args, **kwargs) func(*args, **kwargs) setattr(model, name, nested_func) else: setattr(model, name, func)
两种方案修改后,你在on_pad状态调用rocket.launch()时,都不会再执行launch方法的打印逻辑,只会直接抛出MachineError异常。
内容的提问来源于stack exchange,提问作者Josh Alexander
相关产品推荐
相关产品推荐

