using wxpython with non-GUI applications

You got it.

···

-----Original Message-----
From: Robin Dunn [mailto:robin@alldunn.com]
Sent: Wednesday, January 09, 2008 5:17 PM

Give me a good explanatory sample to put into the demo and I'll add it.

Here's a splash. Perky li'l. Attached & reproduced.

Here's the catch. AsyncCall may deadlock with CallAfter. Current solution
permits 'timeout' and 'failval' arguments. Specifically, in line 56,
AsyncCall().Wait() times out in one second. I observed it three times BTOP
by time of posting, by setting line 69 and holding down Alt-F4, FTA, for the
archives.

Versions MSW XP- Python 2.5.1- wxWidgets 2.8.6.1.

Thanks.

from __future__ import with_statement
import wx
import time
import threading

class AsyncCall:
    from threading import Event
    ''' Queues a func to run in thread of MainLoop.
    Code may wait() on self.complete for self.result to contain
    the result of func(*ar,**kwar). It is set upon completion.
    Wait() does this.'''
    def __init__( self, func, *ar, **kwar ):
        self.noresult= object()
        self.result, self.complete= self.noresult, self.Event()
        self.func, self.ar, self.kwar= func, ar, kwar
        wx.CallAfter( self.TimeToRun )
    def TimeToRun( self ):
        self.result=self.func( *self.ar, **self.kwar )
        self.complete.set()
    def Wait( self, timeout= None, failval= None ):
        self.complete.wait( timeout )
        if self.result is self.noresult:
            return failval
        return self.result

class ThreadEx( threading.Thread ):
    def __init__( self, func ):
        threading.Thread.__init__( self, target= func, args= ( self, ) )
        self.bContinue, self.finishlock= True, threading.Lock()
        self.start()

def BindEx( control, event ):
    def pre( func ):
        control.Bind( event, func )
        return func
    return pre

if __name__== '__main__':
    def main():
        app= wx.PySimpleApp()
        frame= wx.Frame( None, title= "AsyncCall Demo" )
        sizer= wx.BoxSizer( wx.VERTICAL )
        text1= wx.TextCtrl( frame, value= "Change this." )
        sizer.Add( text1, 1, wx.EXPAND )
        gauge1= wx.Gauge( frame )
        sizer.Add( gauge1, 0, wx.ALIGN_CENTER )
        frame.SetSizer( sizer )
        frame.Show()

        @ThreadEx
        def thr1( thr1 ):
            while 1:
                with thr1.finishlock:
                    if not thr1.bContinue: break
                    AsyncCall( gauge1.Pulse ) #do not Wait
                    caption= AsyncCall( text1.GetValue ).Wait( 1 )
                    print 'Text: %s\n'% caption,
                time.sleep( .1 )

        @BindEx( frame, wx.EVT_CLOSE )
        def onclose( event ):
            thr1.bContinue= False
            with thr1.finishlock: pass
            event.Skip()

        app.MainLoop()
        thr1.join()

    if 1:
        main()
    else: #try the line-56 None deadlock timeout return
        while 1:
            main()

asyncable.py (2.25 KB)

···

-----Original Message-----
From: Aaron Brady [mailto:castironpi@comcast.net]
Sent: Wednesday, January 09, 2008 5:21 PM

> -----Original Message-----
> From: Robin Dunn [mailto:robin@alldunn.com]
> Sent: Wednesday, January 09, 2008 5:17 PM
>
> Give me a good explanatory sample to put into the demo and I'll add it.

You got it.