但是,我想知道机器实例的内部状态是否会损坏。
除非您打算使用queued转换功能,否则可以在回调函数中引发异常。
转换按以下顺序执行:
prepare -> conditions -> before -> on_exit -> set_state -> on_enter -> after
如果之前set_state的任何东西引发 Exception 或 in 中的函数conditions没有返回True,则转换将停止。
不过,您的模型可能处于未定义状态。如果您在 or 中依赖一些“清理”或“拆除State.on_enter” after:
from transitions import Machine
class Model:
def __init__(self):
self.busy = False
def before(self):
self.busy = True
raise Exception('oops')
def after(self):
# if state transition is done, reset busy
self.busy = False
model = Model()
m = Machine(model, states=['A','B'], initial='A',
transitions=[{'trigger':'go', 'source':'A', 'dest':'B',
'before':'before', 'after':'after'}])
try:
model.go()
except Exception as e:
print "Exception: %s" % e # Exception: oops
print "State: %s" % model.state # State: A
print "Model busy: %r" % model.busy # Model busy: True
有没有更好的方法向应用程序发出带有具体信息的错误信号?
这取决于您想要达到的目标。引发错误/异常通常会停止当前任务的执行。在我看来,这几乎是传播问题的方式。如果你想处理错误并将错误表示为一种状态,我不会考虑使用conditions丑陋的。具有相同的有效转换trigger按照它们添加的顺序进行评估。考虑到这一点,并且使用unless否定表示法conditions,您的代码可能如下所示:
from transitions import Machine
import os
class Application(object):
states = ["idle", "data_loaded", "filename_invalid", "data_invalid"]
transitions = [
{'trigger': 'filename_dropped', 'source': 'idle',
'dest': 'filename_invalid', 'unless': 'is_valid_filename'},
{'trigger':'filename_dropped', 'source': 'idle',
'dest':'data_invalid', 'unless': 'is_valid_data'},
{'trigger':'filename_dropped', 'source': 'idle',
'dest':'data_loaded'}
]
def __init__(self):
self.data = None
machine = Machine(model=self, states=Application.states,
transitions=Application.transitions, initial="idle")
self.machine = machine
def drop_filename(self, filename):
self.filename_dropped(filename)
if self.is_data_loaded():
print "Data loaded"
# renamed load_data
def is_valid_data(self, filename):
try:
with open(filename) as file:
self.data = file.read()
except IOError as exc:
print "File loading error: %s" % str(exc)
return False
return True
def is_valid_filename(self, filename):
return os.path.isfile(filename)
app = Application()
app.drop_filename('test.txt')
# >>> Data loaded
print app.state
# >>> data_loaded
app.to_idle()
app.drop_filename('missing.txt')
print app.state
# >>> filename_invalid
app.to_idle()
app.drop_filename('secret.txt')
# >>> File loading error: [Errno 13] Permission denied: 'secret.txt'
print app.state
# >>> data_invalid
这将创建这个状态机:
