Python + Windows Automation - Windows иногда дает сбой - PullRequest
2 голосов
/ 18 марта 2011

Я автоматизирую некоторые вещи для Windows с помощью Python, использую PIL для создания скриншотов и тому подобное. проблема в том, что иногда, глубоко в какой-то функции, я делаю time.sleep(1), и приложение с графическим интерфейсом, с которым я взаимодействую, зависает на секунду. Это странно, потому что выполнение time.sleep в других местах не приводит к зависанию. Я не смог точно определить, что вызывает зависание, а что нет .. это произошло как в потоках, кроме основного потока, так и в основном.

Есть идеи? Я чувствую, что мне просто нужна функция «chill out», чтобы заставить Python остановить все, что он делает, позволить целевому пользовательскому интерфейсу восстановиться, обновить и обработать ввод, а затем вернуть его обратно в Python. Какая функция будет делать это? (Похоже, что функция windows Sleep действует так же, как и * python * 1006.)

Ответы [ 3 ]

1 голос
/ 18 марта 2011

Мне кажется, что мне просто нужна функция "chill out", чтобы заставить Python остановить все, что он делает, позволить целевому пользовательскому интерфейсу восстановиться, обновить и обработать ввод, а затем вернуть его обратно в Python.Какая функция будет это делать?

Вызов sleep() (любой его вариант) заблокирует выполнение потока, из которого вы его вызываете.Это просто последнее, что вы хотите сделать, если вы хотите иметь отзывчивый пользовательский интерфейс в этом потоке.Проще говоря, когда вы ложитесь спать, вы ничего не можете сделать!

Если у вас нет неотвечающего пользовательского интерфейса, это означает, что в потоке, который обрабатывает пользовательский интерфейс, выполняется долго выполняемая задача, илипоток пользовательского интерфейса блокируется.Таким образом, чтобы следовать логике, если ваши 1-секундные сны (они на самом деле являются дремами, а не правильными снами!) Приводят к зависанию пользовательского интерфейса, они должны происходить в том же потоке, что и пользовательский интерфейс, или в потоке, которым является пользовательский интерфейс.в ожидании.

Я действительно не знаю, как вы используете PIL и как вы взаимодействуете с приложением, изображение которого вы копируете, но не похоже, что вы внедряете его в этот другой процесс.Так что я предполагаю, что этот процесс ожидает вашего потока.Если это так, то нет реального пути к решению вашей проблемы.Вам просто нужно тратить меньше времени на то, что вы делаете.Звонок sleep() может только усугубить ситуацию.

Звонок SwitchToThread() тоже не может помочь.Все, что он сделает, - это разрешит запуск другого потока (если он ожидает и готов к запуску), но вы хотите, чтобы поток был запущен.В любом случае это не будет иметь большого значения, потому что система будет знать, что ваш поток хочет работать, и будет планировать его снова в свое время.

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

1 голос
/ 19 марта 2011

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

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

def process_messages():
    msg = wintypes.MSG ()
    while user32.GetMessageA (byref (msg), None, 0, 0) != 0:  
        user32.TranslateMessage (byref (msg))
        user32.DispatchMessageA (byref (msg))

Благословенная Microsoft версия здесь . Код доставит события в цикл событий приложения, которое запустило ваш поток, и вернется, когда очередь событий станет пустой.

Я немного искал в Python и сторонних библиотеках реализацию этой функциональности, но не нашел ее при таком быстром поиске.

Короче говоря, вы должны сделать что-то подобное выше при вызове вашей собственной функции process_messages(), как это было сделано в Visual Basic и некоторых других языках только для Windows, и избегать вызова sleep().

p.s. Вы можете настроить насос сообщений, чтобы доставлять сообщения только до тех пор, пока задача, которую вы ожидаете, не будет выполнена.

0 голосов
/ 18 марта 2011

О SwitchToThread кажется многообещающим.Или в языке Python, ctypes.windll.kernel32.SwitchToThread().

РЕДАКТИРОВАТЬ: Хм, кажется, не совсем это ...

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