在 "on_enter" 回调中更改状态时的回调顺序
Order of callbacks when changing state in "on_enter" callback
我使用状态机python实现transitions.
当我尝试在 on_enter 回调中直接更改机器状态时,回调调用的顺序不是我期望的顺序。
请在下面找到发生问题的最小可运行代码:
# coding: utf8
"""Minimal script."""
from transitions.extensions import GraphMachine as Machine
class MyStateMachine(object):
"""My state machine"""
def __init__(self):
"""Initialization."""
super(MyStateMachine, self).__init__()
states = ["state_a", "state_b"]
transitions = [
{
"trigger": "go_b",
"source": "state_a",
"dest": "state_b",
"before": "before",
"after": "after",
},
{
"trigger": "go_a",
"source": "state_b",
"dest": "state_a",
"before": "before",
"after": "after",
},
]
self.__machine = Machine(self, states=states, transitions=transitions,
initial="state_a")
def before(self):
"""Before transition."""
print "before transition"
def after(self):
"""After transition."""
print "after transition - current state:", self.state
def on_enter_state_a(self):
"""When entering in state A."""
print "enter state A"
def on_exit_state_a(self):
"""When exiting state A."""
print "exit state A"
def on_enter_state_b(self):
"""When entering in state A."""
print "enter state B"
self.go_a()
def on_exit_state_b(self):
"""When exiting state A."""
print "exit state B"
def main():
"""Main function."""
machine = MyStateMachine()
machine.go_b()
if __name__ == '__main__':
main()
预期输出:
before transition
exit state A
enter state B
after transition - current state: state_b
before transition
exit state B
enter state A
after transition - current state: state_a
观察到的输出:
before transition
exit state A
enter state B
before transition
exit state B
enter state A
after transition - current state: state_a
after transition - current state: state_a
可以认为这是一个错误吗?
如果不是,我如何获得 expected 输出?
答案:将机器关键字queued
设置为True
从转换 Readme:
The default behaviour in Transitions is to process events instantly. This means events within an on_enter method will be processed before callbacks bound to after are called [...] If queued processing is enabled, a transition will be finished before the next transition is triggered: machine = Machine(states=states, queued=True) [...]
您需要用 queued=True
初始化 Machine
。上面提到的部分涵盖了两种情况下回调的执行顺序,以及启用排队时 Machine
行为的变化。
我将 queued
作为关键字添加到您提供的示例中以说明该过程:
from transitions.extensions import GraphMachine as Machine
class MyStateMachine(object):
"""My state machine"""
# added 'queued' to constructor of custom class...
def __init__(self, queued=False):
"""Initialization."""
super(MyStateMachine, self).__init__()
states = ["state_a", "state_b"]
transitions = [
{
"trigger": "go_b",
"source": "state_a",
"dest": "state_b",
"before": "before",
"after": "after",
},
{
"trigger": "go_a",
"source": "state_b",
"dest": "state_a",
"before": "before",
"after": "after",
},
]
# ... to pass the value to 'Machine'
self.__machine = Machine(self, states=states, transitions=transitions,
initial="state_a", queued=queued)
def before(self):
print "before transition"
def after(self):
print "after transition - current state:", self.state
def on_enter_state_a(self):
print "enter state A"
def on_exit_state_a(self):
print "exit state A"
def on_enter_state_b(self):
print "enter state B"
self.go_a()
def on_exit_state_b(self):
"""When exiting state A."""
print "exit state B"
def main():
print "---- Standard behaviour ----"
machine = MyStateMachine()
machine.go_b()
print "---- Now queued ----"
queued_machine = MyStateMachine(queued=True)
queued_machine.go_b()
if __name__ == '__main__':
main()
输出:
---- Standard behaviour ----
before transition
exit state A
enter state B
before transition
exit state B
enter state A
after transition - current state: state_a
after transition - current state: state_a
---- Now queued ----
before transition
exit state A
enter state B
after transition - current state: state_b
before transition
exit state B
enter state A
after transition - current state: state_a
如果您关心的话:转换支持 logging
这样您就不需要用 print 语句使您的代码混乱:
from transitions.extensions import GraphMachine as Machine
import logging
class Model(object):
def before(self):
pass
def after(self):
pass
logging.basicConfig(level=logging.DEBUG)
model = Model()
machine = Machine(model, states=['A', 'B'], before_state_change='before',
after_state_change='after', initial='A')
model.to_B()
输出:
DEBUG:transitions.core:Initiating transition from state A to state B...
DEBUG:transitions.core:Executed callback 'before' before transition.
DEBUG:transitions.core:Exiting state A. Processing callbacks...
INFO:transitions.core:Exited state A
DEBUG:transitions.core:Entering state B. Processing callbacks...
INFO:transitions.core:Entered state B
DEBUG:transitions.core:Executed callback 'after' after transition.
我使用状态机python实现transitions.
当我尝试在 on_enter 回调中直接更改机器状态时,回调调用的顺序不是我期望的顺序。
请在下面找到发生问题的最小可运行代码:
# coding: utf8
"""Minimal script."""
from transitions.extensions import GraphMachine as Machine
class MyStateMachine(object):
"""My state machine"""
def __init__(self):
"""Initialization."""
super(MyStateMachine, self).__init__()
states = ["state_a", "state_b"]
transitions = [
{
"trigger": "go_b",
"source": "state_a",
"dest": "state_b",
"before": "before",
"after": "after",
},
{
"trigger": "go_a",
"source": "state_b",
"dest": "state_a",
"before": "before",
"after": "after",
},
]
self.__machine = Machine(self, states=states, transitions=transitions,
initial="state_a")
def before(self):
"""Before transition."""
print "before transition"
def after(self):
"""After transition."""
print "after transition - current state:", self.state
def on_enter_state_a(self):
"""When entering in state A."""
print "enter state A"
def on_exit_state_a(self):
"""When exiting state A."""
print "exit state A"
def on_enter_state_b(self):
"""When entering in state A."""
print "enter state B"
self.go_a()
def on_exit_state_b(self):
"""When exiting state A."""
print "exit state B"
def main():
"""Main function."""
machine = MyStateMachine()
machine.go_b()
if __name__ == '__main__':
main()
预期输出:
before transition
exit state A
enter state B
after transition - current state: state_b
before transition
exit state B
enter state A
after transition - current state: state_a
观察到的输出:
before transition
exit state A
enter state B
before transition
exit state B
enter state A
after transition - current state: state_a
after transition - current state: state_a
可以认为这是一个错误吗? 如果不是,我如何获得 expected 输出?
答案:将机器关键字queued
设置为True
从转换 Readme:
The default behaviour in Transitions is to process events instantly. This means events within an on_enter method will be processed before callbacks bound to after are called [...] If queued processing is enabled, a transition will be finished before the next transition is triggered: machine = Machine(states=states, queued=True) [...]
您需要用 queued=True
初始化 Machine
。上面提到的部分涵盖了两种情况下回调的执行顺序,以及启用排队时 Machine
行为的变化。
我将 queued
作为关键字添加到您提供的示例中以说明该过程:
from transitions.extensions import GraphMachine as Machine
class MyStateMachine(object):
"""My state machine"""
# added 'queued' to constructor of custom class...
def __init__(self, queued=False):
"""Initialization."""
super(MyStateMachine, self).__init__()
states = ["state_a", "state_b"]
transitions = [
{
"trigger": "go_b",
"source": "state_a",
"dest": "state_b",
"before": "before",
"after": "after",
},
{
"trigger": "go_a",
"source": "state_b",
"dest": "state_a",
"before": "before",
"after": "after",
},
]
# ... to pass the value to 'Machine'
self.__machine = Machine(self, states=states, transitions=transitions,
initial="state_a", queued=queued)
def before(self):
print "before transition"
def after(self):
print "after transition - current state:", self.state
def on_enter_state_a(self):
print "enter state A"
def on_exit_state_a(self):
print "exit state A"
def on_enter_state_b(self):
print "enter state B"
self.go_a()
def on_exit_state_b(self):
"""When exiting state A."""
print "exit state B"
def main():
print "---- Standard behaviour ----"
machine = MyStateMachine()
machine.go_b()
print "---- Now queued ----"
queued_machine = MyStateMachine(queued=True)
queued_machine.go_b()
if __name__ == '__main__':
main()
输出:
---- Standard behaviour ----
before transition
exit state A
enter state B
before transition
exit state B
enter state A
after transition - current state: state_a
after transition - current state: state_a
---- Now queued ----
before transition
exit state A
enter state B
after transition - current state: state_b
before transition
exit state B
enter state A
after transition - current state: state_a
如果您关心的话:转换支持 logging
这样您就不需要用 print 语句使您的代码混乱:
from transitions.extensions import GraphMachine as Machine
import logging
class Model(object):
def before(self):
pass
def after(self):
pass
logging.basicConfig(level=logging.DEBUG)
model = Model()
machine = Machine(model, states=['A', 'B'], before_state_change='before',
after_state_change='after', initial='A')
model.to_B()
输出:
DEBUG:transitions.core:Initiating transition from state A to state B...
DEBUG:transitions.core:Executed callback 'before' before transition.
DEBUG:transitions.core:Exiting state A. Processing callbacks...
INFO:transitions.core:Exited state A
DEBUG:transitions.core:Entering state B. Processing callbacks...
INFO:transitions.core:Entered state B
DEBUG:transitions.core:Executed callback 'after' after transition.