Как реализовать функцию паузы (и многое другое)?

Приношу свои извинения заранее за объем вопроса, я не хотел ничего упускать.

Некоторая справочная информация

Я пытаюсь автоматизировать процесс ввода данных, написав приложение Python, которое использует Windows API для имитации нажатия клавиш, движения мыши и манипуляций с окном / элементами управления. Мне приходится прибегать к этому методу, потому что у меня (пока) нет уровня допуска, необходимого для доступа к хранилищу данных / базе данных напрямую (например, с использованием SQL) или косвенно через более подходящий API. Бюрократия, это боль; -)

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

Изначально я хочу, чтобы человек мог отслеживать процесс автоматического ввода данных, чтобы убедиться, что все идет правильно. Для этого я, с одной стороны, замедляю действия, но также информирую пользователя о том, что в данный момент происходит, через закрепленное окно.

Фактический вопрос

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

ОБНОВЛЕНИЕ [23/01]: Я действительно хочу сделать больше, чем просто приостановить, я хочу иметь возможность общаться с процессом автоматизации во время его работы и попросить его приостановить, пропустить текущий заказ на продажу, полностью отказаться и, возможно, даже больше.

Кто-нибудь может показать мне правильный путь (TM), чтобы достичь того, чего я хочу?

Дополнительная информация

Вот пример того, как работает автоматизация (я использую библиотеку pywinauto ):

from pywinauto import application
app = application.Application()
app.start_("notepad")
app.Notepad.TypeKeys("abcdef")

ОБНОВЛЕНИЕ [25/01]: После нескольких дней работы над моим приложением я заметил, что не 'Я действительно не использую pywinauto так часто, прямо сейчас я' m, используя его только для поиска окна, а затем я напрямую использую SendKeysCtypes.SendKeys для имитации ввода с клавиатуры и функции win32api для имитации ввода с помощью мыши.

То, что я выяснил до сих пор.

Вот несколько методов, с которыми я столкнулся до сих пор в поисках ответа:

  1. Я мог бы разделить функции автоматизации и интерфейс + прослушиватель горячих клавиш в двух отдельных процессах. Назовем первого «автоматом», а второго «менеджером». Затем менеджер может приостановить выполнение автомата, отправив процессу сигнал SIGSTOP, и возобновить его с помощью сигнала SIGCONT (или его эквивалентов в Windows через SuspendThread / ResumeThread).

    Чтобы иметь возможность обновлять пользовательский интерфейс, автоматизатору необходимо будет информировать менеджера о своем продвижении через какой-то механизм IPC.

    Минусы:

    • Будет ли использование SIGSTOP немного резким? Будет ли он работать нормально? Многие люди, кажется, отговаривают это и даже называют это «опасным».

    • Я обеспокоен тем, что реализация механизма IPC будет немного сложной. С другой стороны, я работал с DBus, что было бы несложно реализовать.

  2. Второй метод, который, кажется, предлагают многие, включает использование потоков и, по сути, сводится к следующему (упрощенно):

     пока True: 
    
    
    • Не будет ли использование SIGSTOP немного жестким? Будет ли он работать нормально? Многие люди, кажется, отговаривают это и даже называют это «опасным».

    • Я обеспокоен тем, что реализация механизма IPC будет немного сложной. С другой стороны, я работал с DBus, что было бы несложно реализовать.

  3. Второй метод, который, кажется, предлагают многие, включает использование потоков и, по сути, сводится к следующему (упрощенно):

     пока True: 
    
    
    • Не будет ли использование SIGSTOP немного жестким? Будет ли он работать нормально? Многие люди, кажется, отговаривают это и даже называют это «опасным».

    • Я обеспокоен тем, что реализация механизма IPC будет немного сложной. С другой стороны, я работал с DBus, что было бы несложно реализовать.

  4. Второй метод, который, кажется, предлагают многие, включает использование потоков и, по сути, сводится к следующему (упрощенно):

     пока True:
     если self.pause: # пауза
     # Выполнять работу...
    

    Однако, делая это таким образом, кажется, что он будет приостановлен только после того, как больше не будет работать. Единственный способ, которым, на мой взгляд, будет работать, - это разделить работу (весь процесс автоматизации) на более мелкие рабочие сегменты (т.е. задачи). Перед запуском новой задачи рабочий поток проверит, следует ли ему остановиться и ждать.

    Минусы:

    • Похоже, реализация для разделения работы на более мелкие сегменты, такие как приведенный выше, была бы очень некрасивой с точки зрения кода (эстетически).

      Как я себе это представляю, все операторы будут преобразованы так, чтобы выглядеть примерно так: queue.put ((function, args)) (например, queue.put ((app.Notepad.TypeKeys , "abcdef")) ), и у вас будет поток процесса автоматизации, выполняющий задачи и непрерывно проверяющий состояние паузы перед запуском задачи. Это просто не может быть правдой ...

    • Программа не остановится как вкопанная, а сначала завершит задачу (пусть даже небольшую) перед тем, как фактически приостановиться.

Достигнутый прогресс

ОБНОВЛЕНИЕ [23 / 01]: Я реализовал версию своего приложения, используя первый метод с помощью упомянутой функции SuspendThread / ResumeThread . Пока что это работает очень хорошо, а также позволяет мне писать элементы автоматизации, как если бы вы писали любой другой скрипт. Единственная странность, с которой я столкнулся, заключается в том, что модификаторы клавиатуры (CTRL, ALT, SHIFT) «застревают» во время паузы. Что-то, что я, вероятно, легко смогу обойти.

Я также написал тест, используя второй метод (потоки и сигналы / передача сообщений), и реализовал функцию паузы. Однако, это выглядит действительно некрасиво (как проверка флажка паузы, так и всего, что связано с «выполнением работы»). Так что, если кто-нибудь может показать мне подходящий пример чего-то похожего на второй метод, я был бы признателен.

Связанные вопросы

13
задан 18 revs 23 May 2017 в 10:26
поделиться