Fwd: oddness question for threading in pyw

limodou limodou at gmail.com
Mon Dec 26 09:42:24 EST 2005


I forward this letter from wxPython maillist, because it seems that no
one answers my question, so I want to ask somebody for help in here.
Thanks.

---------- Forwarded message ----------
From: limodou <limodou at gmail.com>
Date: 2005-12-26 下午3:06
Subject: oddness question for threading in pyw
To: wxpython-users at lists.wxwidgets.org


When I'm dealing theading program in wxPython, I find an oddness
question. If the python filename is '.pyw' suffixed, and the thread is
set as daemon, when I double clicked it to run, the thread object
seems be blocked till I exit the program. But if the thread is not set
as daemon, every thing is ok. But if the python filename is not '.pyw'
suffixed, but '.py', the question is disappeared. Can anybody explain
it for me, and how to resolved it? Need I change the deamon to false?

There is a testing program, which I modified from the wxPython Threading Demo.

import  random
import  time
import  thread
import threading

import  wx
import  wx.lib.newevent

#----------------------------------------------------------------------

# This creates a new Event class and a EVT binder function
(UpdateBarEvent, EVT_UPDATE_BARGRAPH) = wx.lib.newevent.NewEvent()


#----------------------------------------------------------------------

class CalcBarThread(threading.Thread):
    def __init__(self, win, barNum, val):
        threading.Thread.__init__(self, name="CalcBarThread")
        self.win = win
        self.barNum = barNum
        self.val = val
        self.keepGoing = self.running = True

    def Start(self):
        self.keepGoing = self.running = True
        thread.start_new_thread(self.Run, ())

    def Stop(self):
        self.keepGoing = False

    def IsRunning(self):
        return self.running

    def run(self):
        while self.keepGoing:
            evt = UpdateBarEvent(barNum = self.barNum, value = int(self.val))
            wx.PostEvent(self.win, evt)

            sleeptime = (random.random() * 2) + 0.5
            time.sleep(sleeptime/4)

            sleeptime = sleeptime * 5
            if int(random.random() * 2):
                self.val = self.val + sleeptime
            else:
                self.val = self.val - sleeptime

            if self.val < 0: self.val = 0
            if self.val > 300: self.val = 300

        self.running = False

#----------------------------------------------------------------------


class GraphWindow(wx.Window):
    def __init__(self, parent, labels):
        wx.Window.__init__(self, parent, -1)

        self.values = []
        for label in labels:
            self.values.append((label, 0))

        font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
        self.SetFont(font)

        self.colors = [ wx.RED, wx.GREEN, wx.BLUE, wx.CYAN,
                        "Yellow", "Navy" ]

        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
        self.Bind(wx.EVT_PAINT, self.OnPaint)


    def SetValue(self, index, value):
        assert index < len(self.values)
        cur = self.values[index]
        self.values[index:index+1] = [(cur[0], value)]


    def SetFont(self, font):
        wx.Window.SetFont(self, font)
        wmax = hmax = 0
        for label, val in self.values:
            w,h = self.GetTextExtent(label)
            if w > wmax: wmax = w
            if h > hmax: hmax = h
        self.linePos = wmax + 10
        self.barHeight = hmax


    def GetBestHeight(self):
        return 2 * (self.barHeight + 1) * len(self.values)


    def Draw(self, dc, size):
        dc.SetFont(self.GetFont())
        dc.SetTextForeground(wx.BLUE)
        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
        dc.Clear()
        dc.SetPen(wx.Pen(wx.BLACK, 3, wx.SOLID))
        dc.DrawLine(self.linePos, 0, self.linePos, size.height-10)

        bh = ypos = self.barHeight
        for x in range(len(self.values)):
            label, val = self.values[x]
            dc.DrawText(label, 5, ypos)

            if val:
                color = self.colors[ x % len(self.colors) ]
                dc.SetPen(wx.Pen(color))
                dc.SetBrush(wx.Brush(color))
                dc.DrawRectangle(self.linePos+3, ypos, val, bh)

            ypos = ypos + 2*bh
            if ypos > size[1]-10:
                break


    def OnPaint(self, evt):
        width, height = size =self.GetSize()
        bmp = wx.EmptyBitmap(width, height)

        dc = wx.MemoryDC()
        dc.SelectObject(bmp)


        self.Draw(dc, size)

        wdc = wx.PaintDC(self)
        wdc.BeginDrawing()
        wdc.Blit(0,0, size[0], size[1], dc, 0,0)
        wdc.EndDrawing()

        dc.SelectObject(wx.NullBitmap)


    def OnEraseBackground(self, evt):
        pass




#----------------------------------------------------------------------

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "Thread Test", size=(450,300))
        self.log = log

        #self.CenterOnParent()

        panel = wx.Panel(self, -1)
        panel.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
        wx.StaticText(panel, -1,
                     "This demo shows multiple threads interacting with this\n"
                     "window by sending events to it, one thread for each bar.",
                     (5,5))
        panel.Fit()

        self.graph = GraphWindow(self, ['Zero', 'One', 'Two', 'Three', 'Four',
                                        'Five', 'Six', 'Seven'])
        self.graph.SetSize((450, self.graph.GetBestHeight()))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(panel, 0, wx.EXPAND)
        sizer.Add(self.graph, 1, wx.EXPAND)

        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        sizer.Fit(self)

        self.Bind(EVT_UPDATE_BARGRAPH, self.OnUpdate)

        self.threads = []
        self.threads.append(CalcBarThread(self, 0, 50))
        self.threads.append(CalcBarThread(self, 1, 75))
        self.threads.append(CalcBarThread(self, 2, 100))
        self.threads.append(CalcBarThread(self, 3, 150))
        self.threads.append(CalcBarThread(self, 4, 225))
        self.threads.append(CalcBarThread(self, 5, 300))
        self.threads.append(CalcBarThread(self, 6, 250))
        self.threads.append(CalcBarThread(self, 7, 175))

        for t in self.threads:
#            t.setDeamon(True)
            t.start()

        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)


    def OnUpdate(self, evt):
        self.graph.SetValue(evt.barNum, evt.value)
        self.graph.Refresh(False)


    def OnCloseWindow(self, evt):
        busy = wx.BusyInfo("One moment please, waiting for threads to die...")
        wx.Yield()

        for t in self.threads:
            t.Stop()

        running = 1

        while running:
            running = 0

            for t in self.threads:
                running = running + t.IsRunning()

            time.sleep(0.1)

        self.Destroy()



#---------------------------------------------------------------------------

class wxApp(wx.App):
    def OnInit(self):
        frame = TestFrame(None, None)
        frame.Show()
        self.SetTopWindow(frame)
        return True

if __name__ == '__main__':
    app = wxApp(0)
    app.MainLoop()


Please note that if I change the code:

        for t in self.threads:
#            t.setDeamon(True)
            t.start()

to

        for t in self.threads:
            t.setDeamon(True)
            t.start()

you will see the problem.

Thanks a lot.
--
I like python!
My Blog: http://www.donews.net/limodou
NewEdit Maillist: http://groups.google.com/group/NewEdit


--
I like python!
My Blog: http://www.donews.net/limodou
NewEdit Maillist: http://groups.google.com/group/NewEdit


More information about the Python-list mailing list