what is the best practice to separate Pygtk and long running thread code

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • seb

    what is the best practice to separate Pygtk and long running thread code

    Hi,

    I am using pygtk for the first times.

    I am wondering what would be the best "pattern" to interface pygtk with
    a thread.

    The thread is collecting informations (over the network for example) or
    is doing some long calculations.

    I would like also to separate the gui part to the action part so that I
    should be easier to maintain.

    *************** *************** *************** ***************
    What should be the best practice in order to achieve this ?
    *************** *************** *************** **************

    What I use now is :



    1)
    the gui is launching the "action" evrey 1 sec and is checking for
    message using a queue every second also.

    gui.py

    .....etc ...
    class window1(SimpleG ladeApp):
    #@-- class window1 }
    #@-- init window1.__init_ _ {
    def __init__(self, path='gui.glade ',
    root='window1',
    domain=app_name , kwargs={}):
    path = os.path.join(gl ade_dir, path)
    SimpleGladeApp. __init__(self, path, root, domain, **kwargs)
    self.q=Queue.Qu eue()
    self.action=act .action(self.q)
    gobject.timeout _add (1000,self.acti on.go) # this is the action
    asked
    gobject.timeout _add (1000,self.proc ess) # check if a new message is
    available in the queue

    def process (self):
    dir (self.q)
    if self.q.empty() == False :
    print "from main ",self.q.ge t()
    return True

    ...etc ....

    2)
    The action part is making somehow the interface between the running
    thread and the gui :
    It puts the new information in the queue for the gui to process it
    later.


    action.py

    import os
    import gui
    import time
    import Queue
    import Spethread # thread that always run in the background

    class Singleton(objec t):
    _instance = None
    def __new__(cls, *args, **kwargs):
    if not cls._instance:
    cls._instance = super(Singleton , cls).__new__(cl s, *args,
    **kwargs)
    return cls._instance


    class action(Singleto n):
    def __init__(self, queue):
    self.q=queue
    self.thread_seb =Spethread.work er()
    self.thread_seb .start()
    self.go()

    def go(self):
    if self.thread_seb :
    reponse=self.th read_seb.status ()
    self.q.put(repo nse)
    else :
    self.q.put("le thread n'existe plus ")
    return True

    def stop(self):
    self.thread_seb .die()


    3)
    The thread part is "just" a thread that should from time to time
    time.Sleep in order for action to query if it has some new messages.

    Spethread.py

    import threading
    import time

    class worker(threadin g.Thread):

    def __init__(self):
    threading.Threa d.__init__(self )
    self.value=0
    self.go_on=1

    def run(self):
    print "self.go_on=",s elf.go_on
    while self.go_on == 1:
    self.value=int( time.time())
    res=2
    for i in range(0, 100):
    res=res^i
    print res
    time.Sleep(0.01 )
    def status(self):
    return self.value


    def die(self):
    print "die request"
    self.go_on=0


    Thanks in advance for sharing this informations.
    Sebastien.

    PS :
    the entire gui.py

    gH#@-- python gui.py {
    #@-- header gui.py {
    #!/usr/bin/env python
    # -*- coding: UTF8 -*-

    # Python module gui.py
    # Autogenerated from gui.glade
    # Generated on Wed Sep 20 22:03:00 2006

    # Warning: Do not modify any context comment beginning with # @--
    # They are required to keep user's code
    # Doing so will make it unable for kefir to help you further manage
    your project

    #@-- header gui.py }
    #@-- app gui {
    import os
    import gobject
    import gtk
    import action as act
    import Queue

    from SimpleGladeApp import SimpleGladeApp, bindtextdomain

    app_name = 'gui'
    app_version = '0.0.1'

    glade_dir = ''
    locale_dir = ''

    bindtextdomain( app_name, locale_dir)

    #@-- app gui }
    #@-- window window1 {
    #@-- class window1 {
    class window1(SimpleG ladeApp):
    #@-- class window1 }
    #@-- init window1.__init_ _ {
    def __init__(self, path='gui.glade ',
    root='window1',
    domain=app_name , kwargs={}):
    path = os.path.join(gl ade_dir, path)
    SimpleGladeApp. __init__(self, path, root, domain, **kwargs)
    self.q=Queue.Qu eue()
    self.action=act .action(self.q)
    gobject.timeout _add (1000,self.acti on.go)
    gobject.timeout _add (1000,self.proc ess)
    #@-- init window1.__init_ _ }
    #@-- new window1.new {
    def new(self):
    print 'A new %s has been created' % self.__class__. __name__
    #@-- new window1.new }
    #@-- custom window1 {
    # Write your own methods here
    #@-- custom window1 }
    #@-- callback window1.on_butt on1_clicked {
    def on_button1_clic ked(self, widget, args=[]):
    print 'on_button1_cli cked called with self.%s' %
    widget.get_name ()
    self.action.sto p()
    print "arrete de thread"
    #@-- callback window1.on_butt on1_clicked }
    def process (self):
    dir (self.q)
    if self.q.empty() == False :
    print "from main ",self.q.ge t()
    return True

    #@-- window window1 }
    #@-- main gui.py {
    #@-- init main {
    def main():
    #@-- init main }
    #@-- body main {
    Window1 = window1()
    Window1.run()
    #@-- body main }
    #@-- main gui.py }
    #@-- run gui.py {
    if __name__ == '__main__':
    main()
    #@-- run gui.py }
    #@-- python gui.py }



    the glade file:


    <?xml version="1.0" standalone="no" ?<!--*- mode: xml -*-->
    <!DOCTYPE glade-interface SYSTEM
    "http://glade.gnome.org/glade-2.0.dtd">

    <glade-interface>

    <widget class="GtkWindo w" id="window1">
    <property name="visible"> True</property>
    <property name="title" translatable="y es">window1</property>
    <property name="type">GTK _WINDOW_TOPLEVE L</property>
    <property name="window_po sition">GTK_WIN _POS_NONE</property>
    <property name="modal">Fa lse</property>
    <property name="resizable ">True</property>
    <property name="destroy_w ith_parent">Fal se</property>
    <property name="decorated ">True</property>
    <property name="skip_task bar_hint">False </property>
    <property name="skip_page r_hint">False</property>
    <property name="type_hint ">GDK_WINDOW_TY PE_HINT_NORMAL</property>
    <property name="gravity"> GDK_GRAVITY_NOR TH_WEST</property>
    <property name="focus_on_ map">True</property>
    <property name="urgency_h int">False</property>

    <child>
    <widget class="GtkVBox" id="vbox1">
    <property name="visible"> True</property>
    <property name="homogeneo us">False</property>
    <property name="spacing"> 0</property>

    <child>
    <widget class="GtkEntry " id="entry1">
    <property name="visible"> True</property>
    <property name="can_focus ">True</property>
    <property name="editable" >True</property>
    <property name="visibilit y">True</property>
    <property name="max_lengt h">0</property>
    <property name="text" translatable="y es">this is it</property>
    <property name="has_frame ">True</property>
    <property name="invisible _char">*</property>
    <property name="activates _default">False </property>
    </widget>
    <packing>
    <property name="padding"> 0</property>
    <property name="expand">T rue</property>
    <property name="fill">Tru e</property>
    </packing>
    </child>

    <child>
    <widget class="GtkButto n" id="button1">
    <property name="visible"> True</property>
    <property name="can_focus ">True</property>
    <property name="label" translatable="y es">button1</property>
    <property name="use_under line">True</property>
    <property name="relief">G TK_RELIEF_NORMA L</property>
    <property name="focus_on_ click">True</property>
    <signal name="clicked" handler="on_but ton1_clicked"
    last_modificati on_time="Wed, 20 Sep 2006 19:59:06 GMT"/>
    </widget>
    <packing>
    <property name="padding"> 0</property>
    <property name="expand">F alse</property>
    <property name="fill">Fal se</property>
    <property name="pack_type ">GTK_PACK_ END</property>
    </packing>
    </child>
    </widget>
    </child>
    </widget>

    </glade-interface>

  • Thomas Guettler

    #2
    Re: what is the best practice to separate Pygtk and long running thread code

    seb wrote:
    Hi,
    >
    I am using pygtk for the first times.
    >
    I am wondering what would be the best "pattern" to interface pygtk with
    a thread.
    >
    The thread is collecting informations (over the network for example) or
    is doing some long calculations.
    Hi,

    I would use several *processes*. If your scripts runs on Unix/Linux
    you can use select() on the filedescriptors of the processes you created
    with popen. On Windows you need to poll them, but maybe this is
    better than threads, too. With idle_add you can get data from
    the subproceses. It gets called if there are no actions in the
    event-loop.

    HTH,
    Thomas

    --
    Thomas Güttler, http://www.thomas-guettler.de/ http://www.tbz-pariv.de/
    E-Mail: guettli (*) thomas-guettler + de
    Spam Catcher: niemand.leerman n@thomas-guettler.de

    Comment

    • seb

      #3
      Re: what is the best practice to separate Pygtk and long running thread code

      Hi Thomas,

      I am running WinXP so that casting processes and getting their results
      is not so convenient.

      I have tested idle add and it does the job : the thread is running
      whenever there is no activity on the gui.
      I still do not understand how it can be so responsive 'cause the thread
      I am using at the moment do not have any time.sleep(ing) .

      I am afraid I have still to use an intermediate class between the
      computing thread and the gui to send data between the two of them but
      now about all the computing time is devoided to the thread.

      Thanks a lot !!!

      Seb.

      ps : the only mod that I have done to the gui.py in the init is

      def __init__(self, path='gui.glade ',
      root='window1',
      domain=app_name , kwargs={}):
      path = os.path.join(gl ade_dir, path)
      SimpleGladeApp. __init__(self, path, root, domain, **kwargs)
      self.q=Queue.Qu eue()
      self.action=act .action(self.q)
      gobject.idle_ad d(self.action.g o)
      #gobject.timeou t_add (1000,self.acti on.go)
      gobject.timeout _add (1000,self.proc ess)



      Thomas Guettler wrote:
      seb wrote:
      >
      Hi,

      I am using pygtk for the first times.

      I am wondering what would be the best "pattern" to interface pygtk with
      a thread.

      The thread is collecting informations (over the network for example) or
      is doing some long calculations.
      >
      Hi,
      >
      I would use several *processes*. If your scripts runs on Unix/Linux
      you can use select() on the filedescriptors of the processes you created
      with popen. On Windows you need to poll them, but maybe this is
      better than threads, too. With idle_add you can get data from
      the subproceses. It gets called if there are no actions in the
      event-loop.
      >
      HTH,
      Thomas
      >
      --
      Thomas Güttler, http://www.thomas-guettler.de/ http://www.tbz-pariv.de/
      E-Mail: guettli (*) thomas-guettler + de
      Spam Catcher: niemand.leerman n@thomas-guettler.de

      Comment

      • sjdevnull@yahoo.com

        #4
        Re: what is the best practice to separate Pygtk and long running thread code

        seb wrote:
        Hi,
        >
        I am using pygtk for the first times.
        >
        I am wondering what would be the best "pattern" to interface pygtk with
        a thread.
        >
        The thread is collecting informations (over the network for example) or
        is doing some long calculations.
        It sounds like you don't need to share all your memory--any time you're
        trying to "seperate" threads, you probably want to be using processes
        instead.

        Comment

        • seb

          #5
          Re: what is the best practice to separate Pygtk and long running thread code

          Hi,

          I am running on WinXP so that is not so convenient to communicate
          between separate processes.

          In the past I have used blocking files but it may be a slow
          communication way for some applications. It may also be too much
          depending on the disk on which the program is run (network drives with
          different rights).

          It seems that RPC call would do the job but I would have liked
          something simplier (although I did not tried it).

          The best thing would be to have a queue feature that would be be shared
          between processes but as far as I know It does not exists in python.


          Thanks.
          Seb


          Do you know of some features like a queue that
          sjdevnull@yahoo .com wrote:
          seb wrote:
          Hi,

          I am using pygtk for the first times.

          I am wondering what would be the best "pattern" to interface pygtk with
          a thread.

          The thread is collecting informations (over the network for example) or
          is doing some long calculations.
          >
          It sounds like you don't need to share all your memory--any time you're
          trying to "seperate" threads, you probably want to be using processes
          instead.

          Comment

          • Thomas Guettler

            #6
            Re: what is the best practice to separate Pygtk and long running thread code

            seb wrote:
            The best thing would be to have a queue feature that would be be shared
            between processes but as far as I know It does not exists in python.
            There is a queue class to share data between threads:



            --
            Thomas Güttler, http://www.thomas-guettler.de/ http://www.tbz-pariv.de/
            E-Mail: guettli (*) thomas-guettler + de
            Spam Catcher: niemand.leerman n@thomas-guettler.de

            Comment

            • sjdevnull@yahoo.com

              #7
              Re: what is the best practice to separate Pygtk and long running thread code

              seb wrote:
              Hi,
              >
              I am running on WinXP so that is not so convenient to communicate
              between separate processes.
              Can you elaborate?

              Windows offers plenty of IPC possibilities, including interprocess
              mutexes and semaphores. See for instance:


              In the past I've used multiple processes under Python with
              activepython's win32pipe for IPC without problems.

              Comment

              Working...