DevNul_Pavel
Март 13, 2012 11:39:09
Доброго времени суток! Обрисую вкратце проблему, есть PyQt-класс интерфейса,
внутри этого класса порождаются новые потоки
в которых выполняются определенные задачи, которые должны возвращать данные.
Так как работать с GUI из другого потока нельзя, то взаимодействие между потоками происходит
с помощью сигналов\слотов PyQT. При завершении работы в одном из подпотоков к родителю подключается слот,
эммитится сигнал и сразу же отключается (названия сигналов различные, так как подзадачки выполняют разные действия -
запросы к базе данных).
Данная система обмена сообщениями работает, проблем нет.
Но интересует какой-нибудь вариант, позволяющий организовать подобное взаимодействие между потоками на чистом питоне
(в других задачах также требуется выполнение обработки данных в главном потоке, а не вызов метода из дочернего потока для обработки)
Прежде думал взять потокобезопасную очередь (сейчас она уже задействована), в дочерних потоках заполнять ее, а в глвном потоке
периодически опрашивать наличие данных в очереди. Однако здесь меня смущает наличие именно опроса по таймеру, не хочется с этим
связываться с таймером так как длительность работы подзадачек может быть различной.
Существует ли какие-нибудь аналоги PyQt сигналов\слотов на чистом питоне,
для оповещения главного потока, что необходимо выполнить определенный метод??
Например в Objective-C есть специальные методы performSelectorInBackground, вызываемый из главного потока и performSelectorInMainThread вызываемый в дочернем потоке при завершении работы задачи.
DevNul_Pavel
Март 13, 2012 12:15:48
Тема вдоль и поперек уже изъезжена, но информацию по взаимодействию с помощью сообщений\сигналов найти не смог
Андрей Светлов
Март 14, 2012 19:40:08
Проблема в том, что Qt event loop желает знать только о Qt объектах. Поэтому приходится опрашивать по таймеру. QApplication не имеет виртуальной функции onIdle (довольно распространенной в разных GUI) — остается только таймер.
DevNul_Pavel
Март 14, 2012 21:43:02
Кажется нашел решение в стандртной библиотеке Python. Модуль concurrent.futures позволяет выполнить определенную функцию в фоновом потоке, организуя взимодействие с потоками на более высоком уровне.
with ThreadPoolExecutor(max_workers=1) as executor:
future = executor.submit(pow, 323, 1235)
print(future.result())
возврщемый объект future имеет метод add_done_callback(fn)
“Added callables are called in the order that they were added and are always called in a thread belonging to the process that added them.”
Если я правильно понял, то этот коллбек будет вызываться в том потоке, в котором его назначили (в моем случае в главном)
Пока возможности нету проверить
Андрей Светлов
Март 15, 2012 06:27:03
Нет. В потоке-обработчике. Главный поток не имеет средств получить управление тогда, когда рабочий поток что-то посчитал.
DevNul_Pavel
Март 15, 2012 18:15:12
Может знаете какие-нибудь сторонние python- библиотеки, способные организовать подобное взаимодействие между потоками с помощью сигналов, не таская за собой библиотеку pyqt? мне кажется довольно распространенный задача
DevNul_Pavel
Март 15, 2012 18:19:41
Что-нибудь в духе организации очереди задач внутри объекта класса, если не ошибаюсь, так сделано в qt
Андрей Светлов
Март 17, 2012 02:25:53
Проблема в интеграции этого стороннего кода с Qt event loop.
Qt активно такому сопротивляется.
Если же вам подходит приложение без Qt GUI — есть варианты.
DevNul_Pavel
Март 17, 2012 19:09:54
Да, да, интересуют варианты без GUI. Случаем не работали с Celery, времени посмотреть не было детально, но вроде бы под эти цели создавалось.
Ed
Март 18, 2012 00:56:05
multiprocesing.apply_async с колбэком - это часом не то, что вы ищете?