wxpython thread question

M

marcinguy

I am new to threading and python. Currently I am working on a GUI app
that will be a frontend to CLI client.

I want to invoke a method of the class from GUI and run it in the
thread. That works well, the problems is I dont know how can I stop
this operation, thread if the user would like to stop/cancel it.

Here is the code:

..
..
..

class ScanThread:
def __init__(self, txtbox, para):
self.para = para
self.txtbox = txtbox
#print "Init"

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

def Stop(self):
self.keepGoing = False
#print "Stop"

def IsRunning(self):
return self.running
#print "IsRunning"

def Run(self):
if self.keepGoing:
obj=tool.sanner(self.para,self.txtbox);

obj.scan()
obj.attack()
#time.sleep(1)

self.running = False
#print "Run set to false"


..
..
..

def do_Scan(self, event): # wxGlade: MyFrame.<event_handler>
#print "Event handler `do_Scan' not implemented"
self.threads = []
val = self.text_ctrl_1.GetValue()
box = self.text_ctrl_2;
self.threads.append(ScanThread(box,val))
for t in self.threads:
t.Start()
self.Scan.Enable(False)
self.Stop.Enable(True)
self.frame_1_statusbar.SetStatusText("Scanning")
#event.Skip()


def do_Stop(self, event): # wxGlade: MyFrame.<event_handler>
#print "Event handler `do_Stop' not implemented"

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()
#event.Skip()

do_Stop doesn't stop the Thread. Works well if I put the simple code
in the thread (i.e printing text etc), but with CLI class code I am
using, it simply doesn't respond.

Any help and explanation or code sample GREATLY appreciated.

Do I have to rewrite class I am using (CLI client) to work with
threads to make this happen ????

Thanks,
 
D

Dennis Lee Bieber

I'm quite confused...
I am new to threading and python. Currently I am working on a GUI app
that will be a frontend to CLI client.
CLI, to me, means "command line interface/interpreter"... And that,
to me, implies you would be using something like os.system(),
os.popen#(), or the subprocess module to run the client... but then you
say
I want to invoke a method of the class from GUI and run it in the

A method of WHAT class? How did we go from a CLI client to a class
inside the GUI application? And did you create an instance of that class
anywhere?
thread. That works well, the problems is I dont know how can I stop

And worse, how are you planning to run a /method/ in a thread... You
would probably be subclassing threading.Thread, creating instances of
it, and /it/ would run your logic...
this operation, thread if the user would like to stop/cancel it.
Typically, by:

1) having the thread main loop testing a global "kill_all" variable...
while not kill_all:
do one cycle of the thread main process

2) passing a Queue instance to the thread initialization parameters, and
having the thread read messages from that Queue... This is often used
when the thread needs to process more than one cycle, but needs
different data for each cycle. In this case, a "die" sentinal value
would be sent on the Queue
while True
data = theQueue.get()
if data == "die": break

3) passing an Event instance to ...

if subclassing from threading.Thread you have can apply the above
methods to the instances, or initialize as member attribute for each
that starts off in a run mode, and supply methods to change the mode.
The main thread loop is still simply
while self.Run:
do one cycle

Here is the code:

.
.
.

class ScanThread:
Old style class... deprecation impending said:
def __init__(self, txtbox, para):
self.para = para
self.txtbox = txtbox
#print "Init"

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

Recommend you use threading.Thread rather than the lower level
thread module... Furthermore, I'd suggest that you make this CLASS a
subclass of threading.Thread, and have the OUTER code create new
instances of the class as needed rather than trying to do multiple
thread starts from within...
#print "Start"

def Stop(self):
self.keepGoing = False
#print "Stop"

def IsRunning(self):
return self.running
#print "IsRunning"
Shouldn't be needed if using threading.Thread... They have an
isAlive() method.
def Run(self):
if self.keepGoing:
obj=tool.sanner(self.para,self.txtbox);

obj.scan()
obj.attack()
#time.sleep(1)

self.running = False
See above comment; when a Thread expires, isAlive() should return
false
def do_Scan(self, event): # wxGlade: MyFrame.<event_handler>
#print "Event handler `do_Scan' not implemented"
self.threads = []
val = self.text_ctrl_1.GetValue()
box = self.text_ctrl_2;
self.threads.append(ScanThread(box,val))

Note that each time this apparent GUI method is called, you wipe out
the list of thread, and then append ONE ScanThread instance to it...
for t in self.threads:
t.Start()

So there is only the most recent thread available to start...
self.Scan.Enable(False)

So where is this defined... You have an Enable method of some Scan
object that is member of this GUI instance?
self.Stop.Enable(True)

Same comment.
self.frame_1_statusbar.SetStatusText("Scanning")
#event.Skip()


def do_Stop(self, event): # wxGlade: MyFrame.<event_handler>
#print "Event handler `do_Stop' not implemented"

busy = wx.BusyInfo("One moment please, waiting for threads to
die...")
wx.Yield()

for t in self.threads:

There is only one thread available...
t.Stop()

running = 1

while running:
running = 0

These three lines are meaningless...
localvar = 1
while localvar (is not 0)
localvar = 0

for t in self.threads:
running = running + t.IsRunning()
Just use threading.Thread and

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

and forget about counting the ones that haven't exited yet... Or use a
set of Queues and and have each exiting thread send its ID (self) as the
data, loop for the number of threads in existance,

for jnk in range(len(self.threads)):
t = terminationQueue.get()
t.join()
time.sleep(0.1)
#self.Destroy()
#event.Skip()

Any help and explanation or code sample GREATLY appreciated.

Do I have to rewrite class I am using (CLI client) to work with
threads to make this happen ????
Since you haven't shown us a minimal (malfunctioning) sample, we
have no idea what your so-called client is doing... Though that mistake
of resetting self.threads to [] each time may be a major factor...

--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
M

Mike Driscoll

I am new to threading and python. Currently I am working on a GUI app
that will be a frontend to CLI client.

I want to invoke a method of the class from GUI and run it in the
thread. That works well, the problems is I dont know how can I stop
this operation, thread if the user would like to stop/cancel it.

Here is the code:

.
.
.

class ScanThread:
def __init__(self, txtbox, para):
self.para = para
self.txtbox = txtbox
#print "Init"

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

def Stop(self):
self.keepGoing = False
#print "Stop"

def IsRunning(self):
return self.running
#print "IsRunning"

def Run(self):
if self.keepGoing:
obj=tool.sanner(self.para,self.txtbox);

obj.scan()
obj.attack()
#time.sleep(1)

self.running = False
#print "Run set to false"

.
.
.

def do_Scan(self, event): # wxGlade: MyFrame.<event_handler>
#print "Event handler `do_Scan' not implemented"
self.threads = []
val = self.text_ctrl_1.GetValue()
box = self.text_ctrl_2;
self.threads.append(ScanThread(box,val))
for t in self.threads:
t.Start()
self.Scan.Enable(False)
self.Stop.Enable(True)
self.frame_1_statusbar.SetStatusText("Scanning")
#event.Skip()

def do_Stop(self, event): # wxGlade: MyFrame.<event_handler>
#print "Event handler `do_Stop' not implemented"

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()
#event.Skip()

do_Stop doesn't stop the Thread. Works well if I put the simple code
in the thread (i.e printing text etc), but with CLI class code I am
using, it simply doesn't respond.

Any help and explanation or code sample GREATLY appreciated.

Do I have to rewrite class I am using (CLI client) to work with
threads to make this happen ????

Thanks,

This is a confusing post as Dennis pointed out. I am glad he was so
analytical. Anyway, if you had posted to the wxPython list, they
probably would have told you to check out the Demo and the wiki. The
Demo has a threading example called DelayedResult, which shows one way
to "stop" a thread. However, I think Dennis had an excellent
explanation of thread killing as well. The wiki link is below:

http://wiki.wxpython.org/LongRunningTasks

Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top