Как сделать обработчик событий python

Добавил пользователь Алексей Ф.
Обновлено: 04.10.2024

У меня есть несколько python потоков. Один - асинхронная функция, которая получает какие-то данные. Вторая - flask приложение, на стороне которого есть обработчик, который работает с этими данными.

В краткой версии выглядит примерно так:

Насколько я понимаю (поправьте, если не прав), после первой же итерации бесконечного цикла, он зависает, ожидая, что другой поток "разбудит" его, когда обработает данные. Но этого не происходит, т.к. на стороне flask-потока некорректно (точнее вообще никак) работает функция-обработчик. Есть ли какой-то способ наладить их координацию так, что после того, как async_timer встал в режим ожидания, на стороне flask'a запускалась именно функция обработчик?

Добрый день/вечер. Полностью изменил вопрос в соответствии с проблемой. Извиняюсь за дубликат, впредь так делать не буду.

1 ответ 1

Для новичка вы очень уж глубоко копаете. :) Это отлично!

Итак, я не трогаю Ваш asyncio код, единственный комментарий по нему, что секция его описания в части Event Loop указывает, что лучше бы Вы его не использовали, что:

This section is intended mostly for authors of lower-level code, libraries, and frameworks, who need finer control over the event loop behavior.

Отдельный асинхронный обработчик внутри потока Flask.

Вообще-то, нельзя. Не стоит трогать поток Flask. Вот тут, тут и тут есть обсуждения этой темы.

В Вашем коде функция flask_timer вообще никак не запускается - вот и не работает.

Общий вывод: используйте отдельный поток.

Таким образом, у нас есть Flask в основном потоке и два дополнительных потока для нашей задачи. На самом деле, два потока тут вроде как и не нужно - достаточно иметь поток asyncio и в нём устанавливать Event, когда задача завершена, а из функций-обработчиков запросов Flask'a можно проверять Event и забирать данные через Queue (не забывая Lock).

Вот вариант Вашего кода с двумя потоками в дополнение к Flask'у. Один получает данные у другого, и потоки обмениваются сигналами.

webfanat вконтакте
webfanat youtube

tkinter события

tkinter события

Всем привет. В первой статье по питону мы с вами уже использовали метод обработки события 'клик левой кнопки мыши', пример:

- событие, в нашем случае это - нажатие левой кнопки мыши.

- название функции, которая будет вызвана при обработке события

Заметьте что в функции которую мы вызываем через обработчик должен быть обязательно аргумент event(объект события).

Отмечу что обработчик событий через метод bind() мы можем вешать на любые элементы:

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

За прокрутку колесика мыши

За правую кнопку мыши:

Также есть двойной щелчок левой кнопки мыши:

здесь используется событие и как я думаю не трудно догадаться что если мы напишем то это будет двойной клик средней кнопки мыши и двойной клик правой кнопки мыши.

Еще мы можем отслеживать событие перемещения мыши:

За перемещение мыши отвечает событие .

Итак с событиями мыши мы более или менее разобрались теперь переходим к клавишам:

За обработку нажатия клавиши Enter отвечает событие .

Обработка нажатия пробела происходит

через событие . Как вы наверное уже поняли мы можем в качестве события указывать любую латинскую клавишу:

Для обработки всех клавиш мы можем воспользоваться событием

Заметьте что у нас выводятся только символьные и цифровые клавиши. Однако если мы просмотрим объект события event, то увидим что специальные клавиши также обрабатываются этим событием.

На этом дорогие друзья у меня на сегодня все.

Желаю удачи и успехов! Пока!

Оцените статью:

Статьи

Комментарии

Внимание. Комментарий теперь перед публикацией проходит модерацию

Галина

Статья никакая: какой print? Вы для кого его вообще пишете в графическом интерфейсе?

Вячеслав

Все бы так материал излагали. Спасибо большое!

Реклама

Запись экрана

Данное расширение позволяет записывать экран и выводит видео в формате webm

События и сигналы в PyQt5 [Урок №5]

В этой части руководства по программированию с PyQt5

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

События

Все приложения с графическим интерфейсом являются событийно-ориентированными. События вызываются главным образом пользователем приложения. Однако, они могут быть вызваны другими средствами, к примеру подключением к Интернету, диспетчером окон или таймером. Когда мы вызываем метод exec_(), приложение входит в главный цикл. Главный цикл получает события и отправляет их объектам.

В событийной модели имеются три участника:

  • Источник события;
  • Объект события;
  • Цель события.

Источник события – это объект, состояние которого меняется. Он вызывает события. Объект события (событие) внедряет состояние, которое меняется в источнике события. Цель события – это объект, которому требуется уведомление. Объект источника события поручает задачу обработки события цели события.

Чтобы начать работу с событиями, PyQt5 имеет уникальный механизм сигналов и слотов. Сигналы и слоты используют для связи между объектами. Сигнал срабатывает, когда происходит конкретное событие. Слот может быть чем-то, вызываемым средствами Python. Слот вызывается, когда срабатывает его сигнал.

Сигналы и слоты

Это простой пример, демонстрирующий сигналы и слоты в PyQt5.

В нашем примере, мы показываем QtGui.QLCDNumber и QtGui.QSlider. Мы меняем число lcd путём перетаскивания ползунка регулятора.

Здесь мы соединяем сигнал valueChanged слайдера к слоту display числа lcd.

Отправитель – это объект, который посылает сигнал. Получатель – это объект, который получает сигнал. Слот – это метод, который реагирует на сигнал.

Сигнал и слот

Рисунок: Сигнал и слот

Переопределённый обработчик события

События в PyQt5 часто обрабатываются путём переопределённых обработчиков события.

В нашем примере, мы переопределяем обработчик события keyPressEvent().

Если мы кликаем кнопку Esc, приложение завершается.

Отправитель события

Иногда удобно знать, какой виджет является отправителем сигнала. Для этого, PyQt5 имеет метод sender().

Мы имеем две кнопки в нашем примере. В методе buttonClicked() мы определяем, какую кнопку мы нажали, с помощью метода sender().

Обе кнопки подключены к одному слоту.

Мы определяем источник сигнала путём вызова метода sender(). В строке состояния приложения, мы показываем метку нажатой кнопки.

Отправитель события

Рисунок: Отправитель события

Срабатывание сигналов

Объекты, создаваемые из QObject, могут имитировать сигналы. В следующем примере, мы увидим, как мы может имитировать пользовательский сигнал.

Мы создаём новый сигнал, именуемый closeApp. Этот сигнал испускается во время события нажатия кнопки мыши. Сигнал присоединяется к слоту close() класса QMainWindow.

Сигнал создаётся с pyqtSignal() как атрибут класса внешнего класса Communicate.

Пользовательский сигнал closeApp присоединяется к слоту close() класса QMainWindow.

Когда мы кликаем на окне курсором мыши, срабатывает сигнал closeApp. Приложение завершается.

В этой части руководства PyQt5, мы покрыли сигналы и слоты.

Продолжение : Диалоги в PyQt5 [Урок №6]

Прошлый урок : Управление макетом в PyQt5 [Урок №4]

Здравствуйте! Спасибо за уроки, мне очень помогли, но здесь, в Событиях и Сигналах, первоначально я просто завис на уровне понимания из-за того, что в тексте используются прямые кальки с английского.

Читаю "Объекты, создаваемые из QObject, могут имитировать сигналы. В следующем примере, мы увидим, как мы может имитировать пользовательский сигнал" - понимаю "Объекты, создаваемые из QObject, могут ПОДРАЖАТЬ сигналам. В следующем примере, мы увидим, как мы может ПОДРАЖАТЬ пользовательскому сигналу." Долго ничего понять не мог - причём тут имитация? Причём тут подражание? Для чего требуется подражать сигналам?

Пока не посмотрел название метода - emit()! Ну, блин, ну есть же устоявшие слова в русском языке, производные от этого emit: эмиссия - излучение, эмиттер - излучатель, передающая антенна. И вот тогда всё встало на свои места - объект посылает сигналы, как радиопередатчик. Он так же, как и радиопередатчик не знает - примет ли кто его сигнал или нет и не ждёт ответа от принявшего сигнал. А вот слоты - это радиоприёмники, которые можно настроить на приём этих сигналов.


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

Большинство событий, поддерживаемых в настоящее время связаны с командами, и вы можете увидеть конкретные примеры использования этих событий в теме о командах. Чтобы продемонстрировать общую концепцию, как использовать событие я буду использовать более общий случай, который исполняется Fusion, когда активируется рабочая среда. Основные понятия, обсуждаемые ниже, относятся ко всем событиям. Все поддерживаемые события перечислены в справке Fusion API под объектом, который поддерживает это событие.Например, события, связанные с рабочей областью, поддерживаются объектом UserInterface, как показано ниже. Объект UserInterface поддерживает четыре события: workspaceActivated, workspaceDeactivated, workspacePreActivate и workspacePreDeactivate.


Для реализации события нужно добавить функцию "handler" в ваш код и подключить этот обработчик к событию. Fusion будет вызывать функцию обработчика, когда в Fusion действие происходит, которое приводит к выполнению события. Даже если концепция реализации событие является таким же, реальная практика довольно сильно отличается для разных языков. Ниже приведены сценарии JavaScript и Python, которые делают одно и то же: подключаются к событию WorkspaceActivated и реагируют на него, но как вы видите, код довольно различный. Шаги и детали реализации описываются ниже.

JavaScript

Python

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

Строки кода 1-7 JavaScript содержат функцию обработчика событий. Функция называется MyWorkspaceActivatedHandler, но это может быть любое имя. В JavaScript, все обработчики событий реализованы как функции одним аргументом "args". Что передано через этот аргумент args, различается для различных событий и, то как определить, что прошло для конкретного события, обсуждается ниже.

Следующим шагом является подключение обработчика к событию. Это делается в строке 14, где вызывается метод добавления объекта WorkspaceEvent (который возвращается свойством UserInterface.workspaceActivated) и куда передается обработчик события. Когда выполняется код JavaScript, он подключает событие, а затем продолжает работать в фоновом режиме, что позволяет его обработчик быть вызываемым и реагировать на события.

Линии 5-13 кода Python содержат обработчик событий. Для Python обработчик событий реализован как класс. Класс может иметь любое имя, но в этом примере назван MyWorkspaceActivatedHandler. В строке 5 можно увидеть, что класс наследуется от adsk.core.WorkspaceEventHandler. Это класс, который должен быть реализован в для этого события. Определение этого класса, обсуждается ниже.

Метод __init__ класса - как видно на линиях 6-7 - точно одинаковый для всех событий. Метод уведомления также одинаков для всех событий, но, конечно, код реализации в пределах события будет варьироваться в зависимости от того, что вам нужно сделать в ответ на событие. Хотя все события имеют аргумент args, объект, передаваемый через этот аргумент изменяется в зависимости от события. Определение того, какой объект прошел через аргумент args описано ниже.

Следующим шагом является подключение обработчика к событию. Это делается в строках 20-22.Объявление в строке 3, также необходимо, как часть этого. Строка 20 присваивает ссылку на обработчик событий для переменной. Вызывается метод добавления для объекта WorkspaceActivated и передается ссылка переменной на функцию MyWorkspaceActivateHandler . Для того, чтобы удержать обработчик от выхода за рамки и освобождения, он добавляется в список обработчиков, которые объявлены на глобальном уровне в строке 6 и остаются в течении жизни сценария.

Сценарий Python (не надстройка) автоматически прекращаются, когда он выполняется. Чтобы сценарий продолжал работать так, чтобы он мог реагировать на события, вызывается функция autoTerminate в строке 26, со значением Ложь в качестве аргумента, чтобы указать Fusion, что сценарий должен продолжать работать в фоновом режиме.

Как было показано выше, события, поддерживаемые каждым объектом, перечислены в разделе данного объекта.На рисунке ниже, была выбрана ссылка события UserInterface.workspaceActivated, где мы можем видеть, что это событие реализовано в рамках объекта WorkspaceEvent.


Нажатие на ссылки WorkspaceEvent показывает тему ниже, где самым важным является метод add, и он существует для всех типов событий.


Нажатие на ссылку add отображает тему, показанную ниже, где мы видим, что аргумент обработчика имеет тип WorkSpaceEventHandler.Это класс, который должен быть реализован для того, чтобы поддерживать это событие.В Python необходимо указать, какой класс наследует класс обработчика событий, и этот класс, что видно в строке 5 кода Python выше.


Нажатие на ссылку WorkspaceEventHandler, а затем, нажатие на ссылку метода уведомления, отобразит тему, показанную ниже. Интересно здесь то, что аргумент eventArgs метода уведомления возвращает объект WorkspaceEventArgs.


И, перейдя по ссылке для этого объекта, вы можете увидеть, к какой информации вы можете получить доступ через его свойства. В этом случае, важной информацией, которую он предоставляет, является объект WorkSpace, который только что был активирован при помощи свойства рабочего пространства, который используется в примерах программ выше в строке 2 программы JavaScript и строке 9 программы Python.

Читайте также: