Как автоматически перезапустить состояние, если условие перехода не выполнено?

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

Начальное состояние ищет окно графического интерфейса пользователя. Когда окно найдено, конечный автомат переходит в следующее состояние.

введите описание изображения здесь

Обратите внимание на следующий код:

class ScreenScrapper(object):
    window = None

    def is_window_found(self):
        return bool(self.window)

    def state_look_for_window(self):
        window = get_window()  # Returns a bitmap object or None if window is not found
        self.do_work()

    def state_do_work(self):
        print('Do some work!')
        print('Window er: ', self.window)


states = ['dummy', 'state_look_for_window', 'state_do_work']

transitions = [
    {'trigger': 'start', 'source': 'dummy', 'dest': 'state_look_for_window', 'after': 'state_look_for_window'},
    {'trigger': 'do_work', 'source': 'state_look_for_window', 'dest': 'state_do_work', 'conditions': 'is_window_found', 'after': 'state_do_work'},
]

screen_scrapper = ScreenScrapper()
Machine(model=screen_scrapper, states=states, transitions=transitions, initial='dummy')

screen_scrapper.start()

В этом простом примере start меняет состояние с dummy на state_look_for_window. Обратный вызов after будет искать окно и впоследствии изменит состояние на state_do_work. Этот переход имеет условие is_window_found

Вопрос: Как можно state_look_for_window снова выполнить, если условие перехода is_window_found вернет False? Обратите внимание: меня интересует только решение, которое может содержаться в конечном автомате. Другими словами, единственный код снаружи должен оставаться screen_scrapper.start().


person Vingtoft    schedule 24.11.2017    source источник
comment
не должно while not is_window_found работать?   -  person muthan    schedule 24.11.2017
comment
Я думал об этом решении, и оно сработает. Но библиотека переходов очень активно использует условия, поэтому я подозреваю, что должен быть лучший и более правильный способ сделать это, особенно потому, что этот вариант использования очень распространен.   -  person Vingtoft    schedule 24.11.2017


Ответы (2)


Поскольку вам просто нужно перейти из одного состояния в другое, вы можете просто выполнить переход состояния после проверки is_window_found

Я думаю это должно выглядеть так

    def state_look_for_window(self):
    if not is_window_found:
        self.state_look_for_window() 
    else:
        window = get_window()  # Returns a bitmap object or None if window is not found
        self.do_work()
person muthan    schedule 24.11.2017
comment
Это был мой первый подход. Но он возвращает следующую ошибку: RuntimeError: превышена максимальная глубина рекурсии. - person Vingtoft; 24.11.2017
comment
Я не уверен, как работает эта государственная вещь. возможно, добавьте еще один триггер, который переходит из вашего состояния в такое же состояние. а затем вызовите триггер вместо самого метода. Потому что стандартная глубина рекурсии Python не очень велика. - person muthan; 24.11.2017

Я думаю, вы просите «рефлексивный переход», то есть триггер, имеющий то же состояние, что и источник и место назначения. Я бы заменил вашу текущую диаграмму другим состоянием под названием «Window Ready» и указал бы внутренний переход для этого состояния, при котором вы продолжаете циклически перемещаться внутри того же самого, пока не будет найден желаемый графический интерфейс Window.

person dog16lover    schedule 07.01.2019