Вложение в Pytransitions - PullRequest
       10

Вложение в Pytransitions

0 голосов
/ 22 января 2019

Я искал закрытые проблемы на github, SO и googling, чтобы решить эту проблему. Но я не смог решить свою проблему, и это, кажется, правильное место. Я уже открыл вопрос о github, но я не уверен, что это было правильно. Я делаю конечный автомат, который может включать в себя несколько подсостояний, которые также являются конечными автоматами. Так что это в основном сводится к повторному использованию HSM в соответствии с readme .

мой SM самого высокого уровня выглядит так:

from transitions.extensions import LockedHierarchicalMachine as Machine
from coordination.running import RunningStateMachine

logging.basicConfig(level=logging.ERROR)
logging.getLogger("transitions").setLevel(logging.INFO)

class RPPStateMachine(Machine):
    def __init__(self, name):
        self._running = RunningStateMachine()
        self.name = name
        states = [
            "init",
            {"name": "running", "children": self._running},
            "stop",
        ]

        Machine.__init__(self, states=states, initial="init")

        self.add_transition("e_run", "init", "run", after=self.run_machine)
        self.add_transition("e_stop", "*", "stop")

    def run_machine(self):
        self._running.initialize()

Как вы видите конечный автомат с тремя состояниями init, running и stop. Как только событие e_run() отправляется через что-то вроде

machine = RPPStateMachine("my_machine")
machine.e_run()

машина переходит в состояние running.

Я делаю это косвенным образом, потому что я хотел, чтобы все происходило автоматически. e_run() вызывает переход к running, а затем run_machine вызывает initialize метод запущенного класса, который запускает событие для запуска цепочки событий. Ниже я показываю running, и это проясняется.

Таким образом, рабочее состояние определяется как

from transitions.extensions import LockedHierarchicalMachine as Machine
from coordination.test_mode import TestingStateMachine
from coordination.release_mode import ReleaseStateMachine

class RunningStateMachine(Machine):
    def __init__(self):
        self._test_mode = TestingStateMachine()
        self._release_demo = ReleaseStateMachine()
        states = [
            "init",
            "configuration",
            "idle",
            {"name": "test_mode", "children": self._test_mode},
            {"name": "release_mode", "children": self._release_mode},
        ]

        Machine.__init__(self, states=states, initial="init")
        self.add_transition("e_start_running", "init", "configuration", after=self.configuration)
        self.add_transition("e_success_config", "configuration", "idle")
        self.add_transition("e_test_mode", "idle", "test_mode")
        self.add_transition("e_release_mode", "idle", "release_mode")
        self.add_transition("e_start_running", "idle", "init")

    def initialize(self):
        print("Initialization step for running, emitting e_start.")
        self.e_start_running()

    def configuration(self):
        print("Configuring...")
        print( "Current state: " + self.state)

        self.e_success_config()

, который похож на своего родителя, состоит из нескольких состояний и нескольких подсостояний. Я также включил ведение журнала, чтобы увидеть, какие состояния я вхожу и выходить. По моему опыту, вложение конечных автоматов очень полезно, так как вы можете повторно использовать состояния, которые вы написали ранее. Кроме того, по мере роста вашего конечного автомата, он помогает сохранять более модульные вещи. Поэтому ни одно государство не становится огромным и трудным для чтения / понимания.

Итак, необычное поведение в том, что когда вызывается e_run(), я получаю отпечатки

INFO:transitions.core:Entered state running
INFO:transitions.core:Entered state running_init
Initialization step for running, emitting e_start.
INFO:transitions.core:Exited state init
INFO:transitions.core:Entered state configuration
Configuring...
current state: configuration
INFO:transitions.core:Exited state configuration
INFO:transitions.core:Entered state idle

Как видите

machine.state
>>> 'running_init'

, а

machine._running.state
>>> 'idle'

Конечно, я могу переместить определения переходов в родительское состояние, но это не удобно. Я не могу сделать это для всех подсостояний. Очевидно, я хочу, чтобы каждое подсостояние отвечало за свое поведение. Какова общая практика здесь? Это ошибка или предполагаемое поведение?

Как аккуратно вложить конечные автоматы друг в друга?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...