Behaviour¶
See also
New to statecharts? See Core concepts for an overview of how states, transitions, events, and actions fit together.
The StateChart class follows the
SCXML specification by default. The
StateMachine class extends StateChart
but overrides several defaults to preserve backward compatibility with
pre-3.0 code.
The behavioral differences are controlled by class-level attributes. This
design allows a gradual upgrade path: start from StateMachine and
selectively enable spec-compliant behaviors one at a time, or start from
StateChart and get full SCXML compliance out of the box.
Tip
We strongly recommend that new projects use StateChart directly.
Existing projects should consider migrating when possible, as the
SCXML-compliant behavior provides more predictable semantics.
Comparison table¶
Attribute |
|
|
Description |
|---|---|---|---|
|
|
|
Tolerate events that don’t match any transition |
|
|
|
Execute entry/exit actions on self-transitions |
|
|
|
When to update configuration during a microstep |
|
|
|
Catch action errors as |
Each attribute is described below, with cross-references to the pages that cover the topic in depth.
allow_event_without_transition¶
When True (SCXML default), sending an event that does not match any enabled
transition is silently ignored. When False (legacy default), a
TransitionNotAllowed exception is raised, including for unknown event names.
The SCXML spec requires tolerance to unmatched events, as the event-driven model expects that not every event is relevant in every state.
See also
See Conditions for how the engine selects transitions, and Checking enabled events to query which events are currently valid.
enable_self_transition_entries¶
When True (SCXML default), a self-transition
executes the state’s exit and entry actions, just like any other transition.
When False (legacy default), self-transitions skip entry/exit actions.
The SCXML spec treats self-transitions as regular transitions that happen to return to the same state, so entry/exit actions must fire. Use an internal transition if you need a transition that stays in the same state without running exit/entry actions.
See also
See Transitions for the full reference on self-transitions and internal transitions.
atomic_configuration_update¶
Controls when the configuration is updated during a microstep.
When False (SCXML default), the configuration reflects each phase as it
happens: states are removed during exit and added during entry. This means
that during transition on callbacks, the configuration may be empty or
partial — the source states have already been exited but the target states
have not yet been entered.
When True (legacy default), the configuration is updated atomically
after the on callbacks complete, so sm.configuration and
state.is_active always reflect a consistent snapshot during the transition.
>>> from statemachine import State, StateChart
>>> class AtomicDemo(StateChart):
... atomic_configuration_update = True
... off = State(initial=True)
... on = State(final=True)
...
... switch = off.to(on, on="check_config")
...
... def check_config(self):
... # With atomic update, configuration is unchanged during 'on'
... self.off_was_active = self.off.is_active
... self.on_was_active = self.on.is_active
>>> sm = AtomicDemo()
>>> sm.send("switch")
>>> sm.off_was_active # source still in configuration during 'on'
True
>>> sm.on_was_active # target not yet in configuration during 'on'
False
With atomic_configuration_update = False (the SCXML default), the result
is different — off.is_active is False because exit already removed it,
and on.is_active is also False because entry hasn’t added it yet.
In this mode, use previous_configuration and new_configuration to
inspect the full picture:
>>> class SCXMLDemo(StateChart):
... off = State(initial=True)
... on = State(final=True)
...
... switch = off.to(on, on="check_config")
...
... def check_config(self, previous_configuration, new_configuration):
... self.prev = {s.id for s in previous_configuration}
... self.new = {s.id for s in new_configuration}
>>> sm = SCXMLDemo()
>>> sm.send("switch")
>>> sm.prev
{'off'}
>>> sm.new
{'on'}
See also
See Dependency injection for the full list of parameters available in callbacks.
catch_errors_as_events¶
When True (SCXML default), runtime exceptions in action callbacks
(entry/exit, transition on) are caught by the engine and dispatched as
internal error.execution events. When False (legacy default), exceptions
propagate normally to the caller.
Note
Validators are not affected by this flag — they
always propagate exceptions to the caller, regardless of the
catch_errors_as_events setting. See Validators for details.
See also
See Error handling for the full error.execution lifecycle,
block-level error catching, and the cleanup/finalize pattern.
Gradual migration¶
All behavioral attributes can be overridden individually. This lets you
adopt SCXML semantics incrementally in an existing StateMachine:
class MyMachine(StateMachine):
catch_errors_as_events = True
# ... everything else behaves as before ...
Or keep a specific legacy behavior while using StateChart for the rest:
class MyChart(StateChart):
atomic_configuration_update = True
# ... SCXML-compliant otherwise ...
See also
See Upgrading from 2.x to 3.0 for a complete migration guide from
StateMachine 2.x to StateChart 3.x.