Форум сайта python.su
Задача - обеспечить параллельную работу программы с сокетами и пользовательским интерфейсом. Т.е. сейчас у меня не получается сделать так, чтобы пользовательский интерфейс не блокировал работу сокетов, с которыми всё нормально. Какие есть варианты для создания UI, не блокируюшего основной цикл программы? Данные из УИ, естественно должны передаваться в основной цикл и наоборот. Подразумевается линукс и венда.
Пробовал - thread, threading, pyGTK. Возможно в pyGTK есть какая-либо функция которая позволяет “опрашивать события” без вызова gtk.main().
Есть мысль про subprocess & communicate(), но как-то неудобно. Да и через PIPE-ы передавать данные не шибко весело.
Офлайн
Qt работает с сокетами в неблокирующем режиме.
Посмотрите примеры с классами QTcpServer и QTcpClient для реализации сервера и клиента соответственно.
Офлайн
Поднимаю тему ещё раз:
Вот примерно что нужно:
...
<создание GUI>
...
while True:
...
<проверка возникновения событий GUI без блокировки и их обработка>
...
...
<уничтожение GUI>
...
Офлайн
Может вам подойдет концепция Idle? Это обработчик вызываемый когда GUI все переделал. http://www.gtk.org/tutorial1.2/gtk_tut-17.html Но наверное проще отстрелить треды которые будут переводить события из сокетов в GUI events. И ваша схема того что надо странная - сам цикл обработки сообщений не блокируется, это скорее вы его блокируете слушая сокеты. Их можно развести поместив цикл обработки сообщений в свой тред (не main).
Отредактировано (Май 5, 2011 19:04:01)
Офлайн
Сокеты через селект слушаются. Селект с задеркой 0.01 секунды - небольшая блокировка, чтоб цикл не жрал проц в холостую, но для пользователя не критичная. GUI в проге только как вспомогательная фича, т.к. вместо GUI может быть управление и через терминал, или вообще GUI \ UI не требуется - всё зависит от конфигурации. Привязывать прогу к ГУИ - нет, привязывать ГУИ к проге - ДА. Поэтому использовать функцию основновного цикла обработки событий ГУИ нельзя вообще никак. Нужна функция именно проверки возникновения событий ГУИ.
С тредами - запарка, т.к. GIL реальных тредов не даёт.
Думаю только насчёт subprocess - реальная параллельная работа. А процессы через опять-же сокеты связать. Геморно - но других выходов нет пока что.
Офлайн
С subprocess будет гемор с передачей данных (они реально в другом процессе). Треды питоновские конечно сильно потеряли привлекательности от GIL, но в вашем случае основное ожидание будет в операционке поэтому GIL почти не будет мешать. Я думаю в вашем случае лучше всего пустить app.mainloop в параллельном треде а из основного треда уведомлять GUI о возникших событиях и в обратную сторону тоже уведомления слать.
rip86ozЯ думаю это заблуждение - треды самые настоящие, Просто часто синхронизируются - по атомарным командам интерпретатора. Может более знающие люди меня поправят.
GIL реальных тредов не даёт
Отредактировано (Май 6, 2011 09:43:23)
Офлайн
Я уже пускал два треда - один с GTK-ым main-ом, второй - свои циклом… что-ж. GTK победил, заблокировав выполнение второго треда.)
С subprocess-ом дело понятное - что в разных процах данные. Но так это не беда - просто трата ресурсов компа на передачу инфы)). От гуи идёт только управление, основная работа и все данные - в другом процессе.
Отредактировано (Май 6, 2011 10:01:44)
Офлайн
1 Будет неплохо посмотреть ваш код
2 как с любыми тредами помоему - надо инициировать процесс переключения. В mainloop на обработку idle можно вставить sleep(0). Это сделает переключения тредов более частым процессом.
Отредактировано (Май 6, 2011 10:13:45)
Офлайн
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
...
Отредактировано (Май 6, 2011 10:33:32)
Офлайн
Ваш код нельзя запустить - поэтому не очень понятно в чем проблема. Не моглибы вы его упростить
def RunGui():
.....
thread_gui=threading.Thread(target=RunGui)
thread_gui.start()
while 1:
myactions()
Отредактировано (Май 6, 2011 10:53:19)
Офлайн