Automat Finite State Machines
Automat provides a declarative, self-service API for defining finite-state machines directly within your Python classes. It helps manage complex state transitions and actions in a structured, testable way. The current version is 25.4.16, and it maintains a relatively stable release cadence with minor updates and bug fixes.
Warnings
- gotcha Failing to call `_machine.initial(self, self.initial_state)` in your class's `__init__` method will result in an uninitialized state machine, preventing any transitions.
- gotcha When defining transitions with `state.upon(input, ...)` if `enter` is omitted, the machine will remain in the *current* state by default. This can be unexpected if you intended a state change.
- gotcha Output methods (decorated with `@_machine.output()`) are instance methods and receive `self` as their first argument. They are called in the context of the instance, allowing them to access and modify instance attributes.
- gotcha Automat discourages directly modifying the machine's state outside of defined inputs and transitions. Attempting to do so breaks the FSM's contract and can lead to unpredictable behavior.
Install
-
pip install automat
Imports
- MethodicalMachine
from automat import MethodicalMachine
Quickstart
from automat import MethodicalMachine
class Door(object):
_machine = MethodicalMachine()
@_machine.state()
def closed(self):
"The door is closed."
@_machine.state()
def open(self):
"The door is open."
@_machine.input()
def open_door(self):
"Open the door."
@_machine.input()
def close_door(self):
"Close the door."
@_machine.output()
def _actuallyOpen(self):
print("The door opens.")
@_machine.output()
def _actuallyClose(self):
print("The door closes.")
closed.upon(open_door, enter=open, outputs=[_actuallyOpen])
open.upon(close_door, enter=closed, outputs=[_actuallyClose])
def __init__(self):
# Crucial: Initialize the machine with an initial state
self._machine.initial(self, self.closed)
# Example usage:
d = Door()
print(f"Initial state: {d._machine.current_state(d)._name}")
d.open_door()
print(f"After open_door: {d._machine.current_state(d)._name}")
d.close_door()
print(f"After close_door: {d._machine.current_state(d)._name}")