Threads in PyGTK: keep typing while ping-ing

bieffe62 at gmail.com bieffe62 at gmail.com
Mon Feb 16 11:56:08 EST 2009


On 16 Feb, 14:47, Mamahita Sela <mamahitas... at yahoo.com> wrote:
> Dear All,
>
> I have read several howtos for threading in PyGTK. I have tried some but with no luck.
>
> What i want is: i can keep typing in gtk.TextView while periodically doing ping some hosts.
>
> I think, the thread part is working since i can ping so fast (even for not reply host, around 3 s for 27 no-reply-host). But, when the ping action is running, i can not typing in textview. What i type while pinging will show up after ping action is done.
>
> (I am using 2.5.1, pygtk 2.10.6 on Linux x86)
>
> This is my code:
> import threading
> import commands
> import gtk
> import gobject
>
> gtk.gdk.threads_init()
>
> class PingHost(threading.Thread):
>     def __init__(self, host):
>         threading.Thread.__init__(self)
>         self.host = host
>         self.result = ()
>     def run(self):
>         self.result = self.host, commands.getstatusoutput('ping %s -c1' %(self.host))[0]
>
> class Main:
>     def __init__(self):
>         self.win = gtk.Window()
>         self.win.connect('destroy', gtk.main_quit)
>         #
>         self.textb = gtk.TextBuffer()
>         self.textv = gtk.TextView(self.textb)
>         self.textv.set_size_request(500, 500)
>         #
>         self.win.add(self.textv)
>         self.win.show_all()
>         #
>         gobject.timeout_add(5000, self.do_ping)
>
>         def do_ping(self):
>         all_threads = []
>         #
>         for h in range(100, 105):
>             host = '192.168.0.%d' %(h)
>             #
>             worker = PingHost(host)
>             worker.start()
>             all_threads.append(worker)
>         #
>         for t in all_threads:
>             t.join()
>             print t.result
>         #
>         return True
>
> if __name__ == '__main__':
>     app = Main()
>     gtk.main()
>
> Any help would be appreciated :)
> Best regards,
> M

As you have been already told, join() blocks until the thread is
terminated. and you should avoid that.
A simple fix could by add a timeout to t.join, doing something like :
        t.join(JOIN_TIMEOUT);
        if not t.isAlive():
            print t.result

Anywway, starting a thread for each ping is not very efficient, so you
could do better by having a 'ping server thread'
that repeatedly performs the following steps:
- accepts ping command on a queue.Queue
- ping the target and waits for the result
- publish the result on another queue.Queue

At this point, the do_ping action should:
  - send a ping command to the oping server
  - check (in non blocking mode) if there is any result on the ping
results queue
  - display the result, if any

Another big speedup would be to avoid spawning a subprocess fro each
ping and instead
using directly sockets to send ICMP packets, using recipes like this :

http://code.activestate.com/recipes/409689/

Ciao
------
FB



More information about the Python-list mailing list