Reputation: 27946
I am using Pytransitions and I have some state machine, for example
from transitions import Machine
from transitions import EventData
class Matter(object):
def __init__(self):
transitions = [
{'trigger': 'heat', 'source': 'solid', 'dest': 'liquid'},
{'trigger': 'heat', 'source': 'liquid', 'dest': 'gas'},
{'trigger': 'cool', 'source': 'gas', 'dest': 'liquid'},
{'trigger': 'cool', 'source': 'liquid', 'dest': 'solid'}
]
self.machine = Machine(
model=self,
states=['solid', 'liquid', 'gas'],
transitions=transitions,
initial='solid',
send_event=True
)
def on_enter_gas(self, event: EventData):
print(f"entering gas from {event.transition.source}")
def on_enter_liquid(self, event: EventData):
print(f"entering liquid from {event.transition.source}")
def on_enter_solid(self, event: EventData):
print(f"entering solid from {event.transition.source}")
Is there some library-supported way to keep track of all the history of the states?
What I am manually doing now is on init:
after_state_change=lambda event: self._on_after_state_change(event)
and
def _on_after_state_change(self, event: EventData):
to_state = event.transition.dest
self._history_df.append({
"start_index": self._index,
"state": to_state
}, ignore_index=True)
I was wondering if the library supported some query-able logging, meaning not just dumping events to a file, but also being able to keep them in a list for example.
Upvotes: 1
Views: 1043
Reputation: 2273
Transitions does not feature a built-in history. If you just want to track the previous states, this GitHub issue might be helpful:
Since the stateful object with transitions is the model you can use the state property to track state changes:
from transitions import Machine
import collections
# if you like your machine to act as a model, let Model inherit from Machine
class Model(object):
def __init__(self, history_length):
self.state_history = collections.deque(maxlen=history_length)
@property
def state(self):
return self.state_history[-1]
@state.setter
def state(self, value):
self.state_history.append(value)
model = Model(3)
machine = Machine(model, states=['A', 'B', 'C', 'D'], initial='A')
print(model.state) # >>> A
model.to_B()
model.to_C()
model.to_A()
model.to_D()
print("->".join(model.state_history)) # >>> C->A->D
This only works with model_attribute='state'
(default value). In case you altered the name of the 'stateful' model field, you need to adjust the above mentioned properties accordingly.
If you are interested in all EventData
, your approach seems to be the go to solution. You can omit the lambda though. after_state_change=self._on_after_state_change
or after_state_change='_on_after_state_change'
(if the method is part of the model) should be enough.
The above mentioned dequeue
(or queue.Queue
) is 'queryable' in a way that you can use filters or list comprehensions with it. If you need something more sophisticated, pandas (which you probably already use considering your history name) or sqlite might be more suitable.
Upvotes: 2