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