rip86oz
Апрель 21, 2011 16:07:42
Задача - обеспечить параллельную работу программы с сокетами и пользовательским интерфейсом. Т.е. сейчас у меня не получается сделать так, чтобы пользовательский интерфейс не блокировал работу сокетов, с которыми всё нормально. Какие есть варианты для создания UI, не блокируюшего основной цикл программы? Данные из УИ, естественно должны передаваться в основной цикл и наоборот. Подразумевается линукс и венда.
Пробовал - thread, threading, pyGTK. Возможно в pyGTK есть какая-либо функция которая позволяет “опрашивать события” без вызова gtk.main().
Есть мысль про subprocess & communicate(), но как-то неудобно. Да и через PIPE-ы передавать данные не шибко весело.
dimabest
Апрель 21, 2011 22:54:18
Qt работает с сокетами в неблокирующем режиме.
Посмотрите примеры с классами QTcpServer и QTcpClient для реализации сервера и клиента соответственно.
rip86oz
Май 5, 2011 16:45:46
Поднимаю тему ещё раз:
Вот примерно что нужно:
...
<создание GUI>
...
while True:
...
<проверка возникновения событий GUI без блокировки и их обработка>
...
...
<уничтожение GUI>
...
doza_and
Май 5, 2011 18:59:52
Может вам подойдет концепция Idle? Это обработчик вызываемый когда GUI все переделал.
http://www.gtk.org/tutorial1.2/gtk_tut-17.html Но наверное проще отстрелить треды которые будут переводить события из сокетов в GUI events. И ваша схема того что надо странная - сам цикл обработки сообщений не блокируется, это скорее вы его блокируете слушая сокеты. Их можно развести поместив цикл обработки сообщений в свой тред (не main).
rip86oz
Май 6, 2011 09:19:08
Сокеты через селект слушаются. Селект с задеркой 0.01 секунды - небольшая блокировка, чтоб цикл не жрал проц в холостую, но для пользователя не критичная. GUI в проге только как вспомогательная фича, т.к. вместо GUI может быть управление и через терминал, или вообще GUI \ UI не требуется - всё зависит от конфигурации. Привязывать прогу к ГУИ - нет, привязывать ГУИ к проге - ДА. Поэтому использовать функцию основновного цикла обработки событий ГУИ нельзя вообще никак. Нужна функция именно проверки возникновения событий ГУИ.
С тредами - запарка, т.к. GIL реальных тредов не даёт.
Думаю только насчёт subprocess - реальная параллельная работа. А процессы через опять-же сокеты связать. Геморно - но других выходов нет пока что.
doza_and
Май 6, 2011 09:38:43
С subprocess будет гемор с передачей данных (они реально в другом процессе). Треды питоновские конечно сильно потеряли привлекательности от GIL, но в вашем случае основное ожидание будет в операционке поэтому GIL почти не будет мешать. Я думаю в вашем случае лучше всего пустить app.mainloop в параллельном треде а из основного треда уведомлять GUI о возникших событиях и в обратную сторону тоже уведомления слать.
rip86oz
GIL реальных тредов не даёт
Я думаю это заблуждение - треды самые настоящие, Просто часто синхронизируются - по атомарным командам интерпретатора. Может более знающие люди меня поправят.
rip86oz
Май 6, 2011 09:53:15
Я уже пускал два треда - один с GTK-ым main-ом, второй - свои циклом… что-ж. GTK победил, заблокировав выполнение второго треда.)
С subprocess-ом дело понятное - что в разных процах данные. Но так это не беда - просто трата ресурсов компа на передачу инфы)). От гуи идёт только управление, основная работа и все данные - в другом процессе.
doza_and
Май 6, 2011 10:09:57
1 Будет неплохо посмотреть ваш код
2 как с любыми тредами помоему - надо инициировать процесс переключения. В mainloop на обработку idle можно вставить sleep(0). Это сделает переключения тредов более частым процессом.
rip86oz
Май 6, 2011 10:32:41
def recurs_mod_loop(pi,i) :
global ilist
global olist
global xdict
global cvars
node = conn_pipes[pi][i]
if not node.inited :
node.init()
if node.inited :
if node.workloop_in() >= 0 :
if i < max_conn_pipes[pi] :
recurs_mod_loop(pi,i+1)
if node.workloop_out() < 0 :
for j in range(0,max_conn_pipes[pi]+1-i) :
rev_conn_pipes[pi][j].close()
else :
for j in range(0,max_conn_pipes[pi]+1-i) :
rev_conn_pipes[pi][j].close()
...
while True :
...
pi = 0
while pi < len(conn_pipes):
...
recurs_mod_loop(pi,0)
...
pi += 1
...
node - есть по сути ячейка программы отвечающая за приём\передачу\обработку данных. ГУИ, сокеты и т.п. могут быть в любых node-ах. Т.е. если где-то node “встревает”, то прога стопорится. Я понимаю, что лучше делать это всё с нормальными тредами на нормальном языке, но надо сделать именно на питоне.
doza_and
Май 6, 2011 10:52:48
Ваш код нельзя запустить - поэтому не очень понятно в чем проблема. Не моглибы вы его упростить
def RunGui():
.....
thread_gui=threading.Thread(target=RunGui)
thread_gui.start()
while 1:
myactions()
ну както так как я написал - чтобы можно было запустить и увидеть проблему.
Стопарение проги хорошо имитируется методом input
А по поводу -нормальных тредов и языка думаю вы не правы - во всех языках есть трудности :)