[wxPython] python interpreter and thread

Hello Ellers

I read your messages about running the python interpreter in a separate
thread. I found your remarks very interesting, because I have the feeling,
they have to do with the application I am developping.

I wrote an interactive python shell using wxPython as GUI (called psi) just
to inderstand how the python interpreter is working. (something like
PyCrust).

I do not know how to explain my problem in correct words; a few exemples
will better illustrate it.

psi is working. But quite early in the development, I noticed a
"problem" between the gui and the interpreter. Roughly speaking,
when the interpreter is working, the GUI is "locked"
and can not be used. Of course, this is not always what we expect.
Let's take an exemple, in psi:

from time import sleep

    for i in range(3):
        print i
        sleep(10)

What does happen? The interpreter is working, and only when it has finished
its job (after 30 seconds), 0, 1, 2 will be printed. The correct way should
be: 0 -ten seconds-
1 -ten seconds-, ...

Another exemple, that is not working in psi:

while 1:

       pass

I am unable to break this infinite loop, since I can not catch any event
coming from the gui.

I do not know how to solve this type of problem. I tried different thing
like using wxYield() to give the hand to the gui, but this does not help to
much. May be I'm using a wrong strategy.
Any idea is welcome.

psi code: Pages Persos Chez.com

Regards
Jean-Michel Fauth, Switzerland

G'day Jean-Michel

I read your messages about running the python interpreter in a separate
thread. I found your remarks very interesting, because I have the feeling,
they have to do with the application I am developping.

I'm glad my (unexpectedly long!) comments were useful. After the heartache I put into that threaded interpreter I'm glad it can help someone
else!

psi is working. But quite early in the development, I noticed a
"problem" between the gui and the interpreter. Roughly speaking,
when the interpreter is working, the GUI is "locked"
and can not be used. Of course, this is not always what we expect.
Let's take an exemple, in psi:

from time import sleep

   for i in range(3):
       print i
       sleep(10)

What does happen? The interpreter is working, and only when it has finished
its job (after 30 seconds), 0, 1, 2 will be printed. The correct way should
be: 0 -ten seconds-
1 -ten seconds-, ...

Yep - this is exactly the multithreading thing. If you multithread your app you will have your GUI interactive at all times, and your print
messages will appear immediately (or close to it).

(There are probably some clever alternatives... but I reckon the investment in multithreading is the best)

Its a bit hard to explain in email (easier on paper or in person) but I'll try...

In a single threaded program there is only one thing being executed at a time - seems simple so far.

So if you do this:

  i = 3
  print i

What you want to happen is eventually this:

  myTextCtrl.Append( "3\n" )

On its own, the above will work.

But if you do this:

  for i in range(1000):
    print i

Its a different story - the one and only thread in your application can't service the GUI because its so busy running the loop.

Another exemple, that is not working in psi:

while 1:

      pass

I am unable to break this infinite loop, since I can not catch any event
coming from the gui.

Yep, you got it.

In the threaded version I can do something like:

  while 1:
    if shell.interrupted( ): break
    shell.sleep( 10 )

or, for a simple animation:

  rotation = 0
  while 1:
    if shell.interrupted( ): break
    studio.setRotation( rotation )
    rotation += 1
    studio.updateDisplay( )
    shell.sleep( 10 )

The two key things here the shell and studio objects. I'd have something like:

class ShellFacade:

  def interrupted( self ):
    return self.isInterrupted # NOTE - should have critical sections here to be safe

  def requestInterrupt( self ):
    self.isInterrupted = 1 # NOTE - should have critical sections here to be safe

  def sleep( self, milli ):
    os.sleep( milli/1000 ) # NOTE - can't remember the proper thing here

and

class StudioFacade:

  def setRotation( self, value ):
     postCommand( SetRotationCommand( value ))

  def updateDisplay( self ):
     postCommand( UpdateDisplayCommand( ))

The StudioFacade, in particular, is my style implementation - you don't have to use command objects but it works for me.

But they key thing points:

- the facade objects (accessible in your shell) communicate back to the main gui thread by posting events. See wxPostEvent.
- the sleep function sleeps in the NON-gui thread (so the GUI is always interactive)
- the interrupted() function allows the loop to be broken.

How to trigger an interrupt?

Something like:

  class MyShellCtrl( wxTextCtrl ):

    ...

    def OnChar( ... )
       if key is control+c or ESCAPE:
         self.interpreter.requestInterrupt( )

I do not know how to solve this type of problem. I tried different thing
like using wxYield() to give the hand to the gui, but this does not help to
much. May be I'm using a wrong strategy.

Yeah - I tried but couldn't figure that out... whilst using threads is a pain to get going it is conceptually much easier to understand (believe it
or not! ...)

Hope this is of some use

Regards
Ellers

>I read your messages about running the python interpreter in a separate
>thread. I found your remarks very interesting, because I have the

feeling,

>they have to do with the application I am developping.

I'm glad my (unexpectedly long!) comments were useful. After the
heartache I put into that threaded interpreter I'm glad it can
help someone else!

I also found it interesting. I wonder if it makes sense to try and move
some of those concepts into PyCrust? Patrick, what do you think?

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

>I read your messages about running the python interpreter in a separate
>thread. I found your remarks very interesting, because I have the

feeling,

>they have to do with the application I am developping.

I'm glad my (unexpectedly long!) comments were useful. After the
heartache I put into that threaded interpreter I'm glad it can
help someone else!

I also found it interesting.

Thanks - thats a big compliment coming from an award winner :wink:

I wonder if it makes sense to try and move
some of those concepts into PyCrust? Patrick, what do you think?

FWIW I may be able to arrange for the existing threaded interpreter code to be released... I can't make any guarantees, but it might be
useful to others.

Ellers

···

7/25/02 4:26:48 AM, "Robin Dunn" <robin@alldunn.com> wrote:

[Ellers]

I'm glad my (unexpectedly long!) comments were useful. After the
heartache I put into that threaded interpreter I'm glad it can
help someone else!

As the author of PyCrust, I'd be very interested in any contributions you
might like to make to support this in PyCrust. Let me know what you think.

···

--
Patrick K. O'Brien
Orbtech
-----------------------------------------------
"Your source for Python programming expertise."
-----------------------------------------------
Web: http://www.orbtech.com/web/pobrien/
Blog: http://www.orbtech.com/blog/pobrien/
Wiki: http://www.orbtech.com/wiki/PatrickOBrien
-----------------------------------------------

[Robin Dunn]

>
> >I read your messages about running the python interpreter in a separate
> >thread. I found your remarks very interesting, because I have the
feeling,
> >they have to do with the application I am developping.
>
> I'm glad my (unexpectedly long!) comments were useful. After the
> heartache I put into that threaded interpreter I'm glad it can
> help someone else!

I also found it interesting. I wonder if it makes sense to try and move
some of those concepts into PyCrust? Patrick, what do you think?

Sorry for the delay in responding. I'm way behind on email. I'd love to see
this feature added to PyCrust. Even better if someone else has already
resolved the issues and could submit a working patch. I'll help out any way
I can, even though I'm pretty busy at the moment.

···

--
Patrick K. O'Brien
Orbtech
-----------------------------------------------
"Your source for Python programming expertise."
-----------------------------------------------
Web: http://www.orbtech.com/web/pobrien/
Blog: http://www.orbtech.com/blog/pobrien/
Wiki: http://www.orbtech.com/wiki/PatrickOBrien
-----------------------------------------------

[Ellers]

> I wonder if it makes sense to try and move
>some of those concepts into PyCrust? Patrick, what do you think?

FWIW I may be able to arrange for the existing threaded
interpreter code to be released... I can't make any guarantees,
but it might be useful to others.

Definitely. You would have my support.

···

--
Patrick K. O'Brien
Orbtech
-----------------------------------------------
"Your source for Python programming expertise."
-----------------------------------------------
Web: http://www.orbtech.com/web/pobrien/
Blog: http://www.orbtech.com/blog/pobrien/
Wiki: http://www.orbtech.com/wiki/PatrickOBrien
-----------------------------------------------