Tkinter and asyncronous socket

M

maxlosblob

Hi all, I'm new to python and I've been spending the last week on GUI
that refresh its content based on data periodically coming from a
remote socket.
I succeded in doing it (thanks newsgroups and online manual!) using
the Tkinter.after method to implement a busy wait on the socket (which
I had previously set to non blocking)
I should be happy with it, but on windows (application must be multi-
platform) the busy wait leads to a 100% CPU usage. I'm trying to
implement it the other way round: a "socket process" that updates a
label (or a queue object) in the GUI. I can't figure out how to do
this. Anyone can post hints? With some details, maybe?

Thanks all

Max
 
S

Steve Holden

Hi all, I'm new to python and I've been spending the last week on GUI
that refresh its content based on data periodically coming from a
remote socket.
I succeded in doing it (thanks newsgroups and online manual!) using
the Tkinter.after method to implement a busy wait on the socket (which
I had previously set to non blocking)
I should be happy with it, but on windows (application must be multi-
platform) the busy wait leads to a 100% CPU usage. I'm trying to
implement it the other way round: a "socket process" that updates a
label (or a queue object) in the GUI. I can't figure out how to do
this. Anyone can post hints? With some details, maybe?
Processes are probably a bit heavyweight for this purpose: they create
difficulties in communication (unless you use the new multiprocessing
library in 2.6).

One approach would be to run the socket code in blocking mode in a
separate thread started by the (main program) GUI thread at program
startup, and communicating results back via a Queue.Queue or similar to
the GUI thread. That thread wakes itself up once every (say) 500 mS to
check for updates from the socket side.

You should see your CPU utilization go down then. The threading.thread
library is actually much easier to use than you would think, though it's
possible to get things wrong by assuming data sharing will work in ways
it actually doesn't. But if you have the main thread pass a Queue to the
networking thread, that should be a reliable means of communication.

regards
Steve
 
M

maxlosblob

Processes are probably a bit heavyweight for this purpose: they create
difficulties in communication (unless you use the new multiprocessing
library in 2.6).

One approach would be to run the socket code in blocking mode in a
separate thread started by the (main program) GUI thread at program
startup, and communicating results back via a Queue.Queue or similar to
the GUI thread. That thread wakes itself up once every (say) 500 mS to
check for updates from the socket side.

You should see your CPU utilization go down then. The threading.thread
library is actually much easier to use than you would think, though it's
possible to get things wrong by assuming data sharing will work in ways
it actually doesn't. But if you have the main thread pass a Queue to the
networking thread, that should be a reliable means of communication.

regards
 Steve

Thankk you Steve, I have now a GUI and a threaded socket client
receiving data on its socket. I pass to it a queue object from the
GUI, but when it tries to push a value on the queue, the GUI does not
see any value. My last work with OOP is as far in time as the
beginning of Java, I'm surely missing something simple but very
important.
Anyway, the goal to have a responsive GUI and a functional socket has
been achieved, thanks again. If you have hints on the queue problem,
your help is welcome.

Bye
Max
 
E

Eric Brunel

If you are not already doing it, you need to make a "stutter thread"
by using the after() call on some gui object to periodically check for
input on the queue.

You don't need to in fact: from the secondary thread, it seems to be safe
to post a user-defined event in the GUI event loop on which you can set a
binding in the GUI thread. This allows a thread switch without having to
do a periodical check.

Here is an example:

------------------------------------
import time
from threading import Thread
from Tkinter import *

root = Tk()

v = IntVar()
v.set(0)

Label(root, width=8, textvariable=v).pack()

def incr_counter(event=None):
v.set(v.get() + 1)

root.bind('<<heartbeat>>', incr_counter)

def heartbeat():
while 1:
time.sleep(1)
root.event_generate('<<heartbeat>>', when='tail')

th = Thread(None, heartbeat)
th.setDaemon(True)
th.start()

root.mainloop()
------------------------------------

The custom event '<<heartbeat>>' is posted in the event loop from the
secondary thread. Note the when='tail' option, which is absolutely
necessary or the binding might be called immediatly without even an actual
event posting. The binding on this event will then be executed in the
thread that launched the mainloop.

HTH
 
H

Hendrik van Rooyen

Thankk you Steve, I have now a GUI and a threaded socket client
receiving data on its socket. I pass to it a queue object from the
GUI, but when it tries to push a value on the queue, the GUI does not
see any value. My last work with OOP is as far in time as the
beginning of Java, I'm surely missing something simple but very
important.
Anyway, the goal to have a responsive GUI and a functional socket has
been achieved, thanks again. If you have hints on the queue problem,
your help is welcome.

If you are not already doing it, you need to make a "stutter thread"
by using the after() call on some gui object to periodically check for
input on the queue.

There is a recipe for this but I have yet again lost the link.

- Hendrik
 
H

Hendrik van Rooyen

Eric Brunel said:
You don't need to in fact: from the secondary thread, it seems to be safe
to post a user-defined event in the GUI event loop on which you can set a
binding in the GUI thread. This allows a thread switch without having to
do a periodical check.
8< ---------------- example -------------
The custom event '<<heartbeat>>' is posted in the event loop from the
secondary thread. Note the when='tail' option, which is absolutely
necessary or the binding might be called immediatly without even an actual
event posting. The binding on this event will then be executed in the
thread that launched the mainloop.


Cunning stuff - I was not aware of this either.

I hope we are not confusing the newbie....

- Hendrik
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top