maemo.org - Talk

maemo.org - Talk (https://talk.maemo.org/index.php)
-   Development (https://talk.maemo.org/forumdisplay.php?f=13)
-   -   Multitasking and GTK with python (https://talk.maemo.org/showthread.php?t=49130)

McLightning 2010-04-03 11:28

Multitasking and GTK with python
 
hi everybody
im using python
i have a problem about "while loops"
but the problem is when i run gtk.main() function it is not allowing me to run another loop. :/ and if i run another loop it is stopping gtk window
:/
def read():
global sock
while 1:
a=sock.recv(1024)
if len(a)==0: break
print a
this is the function i need to run meanwhile gtk is running :/
please help
i googled a lil bit but i couldnt find a proper tutorial on handling multitasking

maacruz 2010-04-03 11:34

Re: Multitasking and GTK with python
 
Look for threads and threading modules in python docs.
Beware that you can only call gtk from the main thread.

McLightning 2010-04-03 12:25

Re: Multitasking and GTK with python
 
class gui(threading.Thread):
__def __init__(self):
____......
____.....
____self.window.show_all()
____threading.Thread.__İnit__(self)
__def run(self):
____gtk.main()

while 1:
__print 'a'
__gui().start()

it supposed to print 'a' forever
but after the gtk window showed up it stopped
please help :/

McLightning 2010-04-03 12:30

Re: Multitasking and GTK with python
 
most of the tutorials on web are about "for loops" and handling them with threading module
but i guess gtk.main() function has a while loop in it

McLightning 2010-04-03 12:34

Re: Multitasking and GTK with python
 
http://www.devshed.com/c/a/Python/Ba...g-in-Python/1/
http://www.wellho.net/solutions/pyth...t-example.html
they are all about for loops

http://stackoverflow.com/questions/8...hile-true-loop
i found this but :/ i didnt get it

omeriko9 2010-04-03 12:48

Re: Multitasking and GTK with python
 
Quote:

Originally Posted by McLightning (Post 593702)

Queue handle multiple threads needs to run at the same time, without the need to take care of locking. If you are not familiar with the term 'lock' in the threads context, you might want to read about that - it's a fundamental part of threading.

Anyway, as you've being said earlier by maacruz, you need to verify that you call gtk.main() from the main thread only, and in the code example you posted, you are not doing that (run() is called by the child threads, therefore gtk.main() is being called by the child threads).

EDIT: to get the expected behavior from the code, replace "print" with the "gtk.main()", and take "gtk.main()" outside the any class or loop (place at the bottom after gui.start()).

EDIT2: There's really no difference between "for", "loop" and "while", all of them interpret to the same assembly calls, just with different handling for the conditions.

McLightning 2010-04-03 13:47

Re: Multitasking and GTK with python
 
import threading
class gui(threading.Thread):
__def __init__(self):
____self.a=0
____.......
____threading.Thread.__init__(self)
__def run(self):
____while 1:
______print self.a
______self.a=self.a+1

gui().start()
gtk.main()

but in this case print function stopping after gtk.main() shows up
im sorry i know im asking a lot :/ :/ im a total noob :/
thanks :) for help

EDIT: it starts to print again after i close gtkwindow

omeriko9 2010-04-03 13:57

Re: Multitasking and GTK with python
 
Quote:

Originally Posted by McLightning (Post 593746)
import threading
class gui(threading.Thread):
__def __init__(self):
____self.a=0
____.......
____threading.Thread.__init__(self)
__def run(self):
____while 1:
______print self.a
______self.a=self.a+1

gui().start()
gtk.main()

but in this case print function stopping after gtk.main() shows up
im sorry i know im asking a lot :/ :/ im a total noob :/
thanks :) for help

EDIT: it starts to print again after i close gtkwindow

It doesn't stop. I think you just can't see it because you see the GUI now.

try adding writing a to a file, you can see it keeps after you see the gui:

Code:

class gui(threading.Thread):
__def __init__(self):
____self.a=0
____.......
____threading.Thread.__init__(self)
__def run(self):
____f = open('/home/user/t.txt', 'a')
____while 1:
______print self.a
______f.write(str(self.a))
______self.a=self.a+1

gui().start()
gtk.main()


McLightning 2010-04-03 14:10

Re: Multitasking and GTK with python
 
no i also see terminal window
i mean terminal window and gtk windows gets opened same time
and i can see terminal windows while gtkwindow is still running in the background

McLightning 2010-04-03 14:15

Re: Multitasking and GTK with python
 
class gui(threading.Thread):
__def __init__(self):
____self.a=0
____.......
____self.entrybox=self.wTree.get_widget('entry2')
____threading.Thread.__init__(self)
__def run(self):
____while 1:
______print self.a
______self.entrybox.set_text(a)
______self.a=self.a+1

gui().start()
gtk.main()

it is not working this way either

EDIT:
from bluetooth import *

class gui(threading.Thread):
__def __init__(self):
____.......
____self.entrybox=self.wTree.get_widget('entry2')
____self.sock=BluetoothSocket(RFCOMM)
____self.sock.connect((host,port))
____print 'connected'

____threading.Thread.__init__(self)
__def run(self):
____while 1:
______data=self.sock.recv(1024)
______self.entrybox.set_text(data)


gui().start()
gtk.main()

what i want is to set this device to send and get data whenever it wants.
i got a button in gui that starts send function and it work OK
but problem is whole about this reading function :/

omeriko9 2010-04-03 14:17

Re: Multitasking and GTK with python
 
Quote:

Originally Posted by McLightning (Post 593767)
class gui(threading.Thread):
__def __init__(self):
____self.a=0
____.......
____self.entrybox=self.wTree.get_widget('entry2')
____threading.Thread.__init__(self)
__def run(self):
____while 1:
______print self.a
______self.entrybox.set_text(a)
______self.a=self.a+1

gui().start()
gtk.main()

it is not working this way either

Can you please post full code, or add as an attachment if it's too long?

epage 2010-04-03 14:22

Re: Multitasking and GTK with python
 
Don't forget to initialize threads with gobject or else (I suspect) it holds on to the GIL while mainloop is processing and doesn't allowing other threads to run.

I've been using
Code:

        gtk.gdk.threads_init()
Also if you ever access GTK from outside of your UI thread, you need to be sure to grab the locks. I use the following helper

Code:

@contextlib.contextmanager
def gtk_lock():
        gtk.gdk.threads_enter()
        try:
                yield
        finally:
                gtk.gdk.threads_leave()

Code:

with gtk_lock():
        # do stuff

If you want an example of a threaded PyGTK program, checkout Dialcentral's source
https://garage.maemo.org/scm/?group_id=657

You can also queue tasks to run in the UI thread from your worker thread using idle_add. I use the following helper

Code:

def async(func):
        """
        Make a function mainloop friendly. the function will be called at the
        next mainloop idle state.
        """

        @functools.wraps(func)
        def new_function(*args, **kwargs):

                def async_function():
                        func(*args, **kwargs)
                        return False

                gobject.idle_add(async_function)

        return new_function

For a more advanced PyGTK threading example than Dialcentral I recommend The One Ring. Though it isn't GTK but DBus based, the principles are the same and the helpers I use in go_utils will work in both.
https://garage.maemo.org/scm/?group_id=1078

McLightning 2010-04-03 14:24

Re: Multitasking and GTK with python
 
Code:

import pygtk
import gtk
import hildon
import gtk.glade
from bluetooth import *
import time,threading
class gui(threading.Thread):
  def gon(self,data=None):
    data=self.got.get_text()
    print data
    if len(data)!=0:
      self.sock.send(data)

  def __init__(self):
    self.a=0
    self.program = hildon.Program()
    self.program.__init__()
    self.window = hildon.Window()
    self.program.add_window(self.window)
    self.window.connect("destroy", gtk.main_quit)
    self.glade_file = "sck.glade"
    self.wTree = gtk.glade.XML(self.glade_file)
    self.got = self.wTree.get_widget("entry1")
    self.al = self.wTree.get_widget("entry2")
    btn = self.wTree.get_widget("button1")
    signals={'clicked':self.send}
    self.wTree.signal_autoconnect(signals)
    self.fx=self.wTree.get_widget("notebook1")       
    self.reparent_loc(self.fx, self.window)
    self.gtkWindow = self.wTree.get_widget("window1")
    self.gtkWindow.destroy()
    self.window.show()
    print 'connecting'
    self.sock=BluetoothSocket(RFCOMM)
    self.sock.connect(('00:1F:00:B5:3A:45',5))
    print "connected."

    threading.Thread.__init__(self)
  def run(self):
    while True:
      self.a=self.a+1
      self.got.set_text(self.a)
      print a
  def reparent_loc(self, widget, newParent):
    widget.reparent(newParent)

gui().start()
gtk.main()

this is the full code

omeriko9 2010-04-03 14:24

Re: Multitasking and GTK with python
 
Also, if you use threads with gtk, you need to call
gtk.gdk.threads_init().

pygtk (binding for python and gtk) holds the GIL (which is kind of a global lock for the process) unless threads_init() is called.

Try adding this line in the __init__.

McLightning 2010-04-03 14:31

Re: Multitasking and GTK with python
 
i posted the full code please could you tell me what should i do about it?
edit:
yeaa great it worked
it worked

THANK YOU ALL :d:d

omeriko9 2010-04-03 14:39

Re: Multitasking and GTK with python
 
Quote:

Originally Posted by McLightning (Post 593784)
i posted the full code please could you tell me what should i do about it?

I suggested what you should do if you want to use threads for background work, aka write to a file or print to the terminal or doing some calculations, but keep all the GUI updates to the main thread (called 'UI thread').

epage mentioned that as well but also extended this to how to handle the GUI itself from within child-threads (also called 'worker threads'), and suggested an alternative - give the gtk to handle your worker threads while it's available using the add_idle example he attached.

An advice - If it's your first work with treads, you might want to know more about threads in general and threads in python before diving into gtk's way for handling threads.

McLightning 2010-04-03 14:41

Re: Multitasking and GTK with python
 
it is great im very excited it worked after adding gtk.gdk.threads_init()
thank you all for all helps
im really appreciated

dannym 2010-04-08 08:52

Re: Multitasking and GTK with python
 
Just use gobject.io_add_watch to be notified when there is data to read and spare yourself the ordeal of using threads.

http://faq.pygtk.org/index.py?req=sh...=faq20.016.htp

def handle_data(source, condition):
__data = source.recv(1024)
__if len(data) > 0:
____self.entrybox.set_text(self.entrybox.get_text( ) + data)
____# or maybe just self.entrybox.props.text += data
____#print data
____return True # call me again if something happens
__else: # end of file
____return False # stop calling me

sock=BluetoothSocket(RFCOMM)
#sock.settimeout(15) # ?
sock.connect(('00:1F:00:B5:3A:45',5))
gobject.io_add_watch(sock, gobject.IO_IN, handle_data)

What happens is that your GUI program ALSO watches your socket and should something arrive, it will call "handle_data" which then reads the chunk that arrived (that is fast).
After that, your GUI program resumes. Note that threads didn't enter the picture anywhere (not in the GTK library either).

McLightning 2010-04-11 19:50

Re: Multitasking and GTK with python
 
i made a couple of apps that im using myself
one is for texting over n95 8gb and received text messages via n95 8gb


All times are GMT. The time now is 22:18.

vBulletin® Version 3.8.8