Python Statemachine
Python Statemachine is an intuitive and powerful library for implementing finite state machines and statecharts. It offers a clean, pythonic, and declarative API for both synchronous and asynchronous Python codebases, supporting advanced features like compound states, parallel regions, history states, and dynamic diagram generation. The library maintains an active development pace with frequent updates and major releases introducing significant new capabilities.
Warnings
- breaking Version 3.0.0 introduces `StateChart` as the new recommended base class for full statechart support (e.g., compound states, parallel regions, history states) and modern defaults. While the older `StateMachine` class is preserved, it maintains 2.x defaults and may not expose all new features. New projects should prefer `StateChart`.
- breaking In version 2.0.0, the `StateMachine.run()` method was removed in favor of `StateMachine.send()` for triggering events. Additionally, the default event processing model changed to 'Run-to-completion (RTC)', which affects how nested events are handled.
- breaking Version 2.0.0 removed `State.identification`, replacing it with `State.id`. State names also became optional, automatically deriving from the class variable name by default.
- gotcha Diagram generation (using `python-statemachine[diagrams]`) requires the external `Graphviz` command-line tool (`dot`) to be installed on your system, in addition to the Python `pydot` dependency.
- deprecated From version 2.2.0, the library warns if non-final states do not have outgoing transitions, indicating potential 'trapped' states. This check is currently a warning but will become an exception by default (`strict_states=True`) in the next major release.
Install
-
pip install python-statemachine -
pip install python-statemachine[diagrams]
Imports
- StateChart
from statemachine import StateChart, State
- StateMachine
from statemachine import StateMachine, State
Quickstart
from statemachine import StateChart, State
class TrafficLightMachine(StateChart):
"A traffic light machine"
green = State(initial=True)
yellow = State()
red = State()
cycle = (
green.to(yellow)
| yellow.to(red)
| red.to(green)
)
def before_cycle(self, event: str, source: State, target: State):
return f"Running {event} from {source.id} to {target.id}"
def on_enter_red(self):
print("Don't move.")
def on_exit_red(self):
print("Go ahead!")
sm = TrafficLightMachine()
print(f"Initial state: {sm.current_state.id}")
print(sm.send("cycle"))
print(f"Current state: {sm.current_state.id}")
print(sm.send("cycle"))
print(f"Current state: {sm.current_state.id}")
print(sm.send("cycle"))
print(f"Current state: {sm.current_state.id}")