[Tutor] Threading in a for loop
Kent Johnson
kent37 at tds.net
Fri Sep 23 00:36:17 CEST 2005
Bill Burns wrote:
> I've got a few questions regarding Threading. I've never used threads
> before and I want to make sure I'm doing it correctly ;-)
>
> I have a GUI app and it processes Tiff files to PDF (or PostScript). The
> GUI has a ListBox which the user populates with files to convert. You
> click on a Button and the file conversion starts. When all the files
> have been converted, the ListBox items (the files) are cleared.
>
> Initially, you had no way of knowing what was going on until all the
> files where cleared from the ListBox.
>
> So I thought of creating threads in the 'for loop' and displaying the
> name of each file in the statusBar of the GUI (as they are being
> processed).
You don't necessarily need threads for this. If you just want to provide feedback and don't care about the GUI being responsive, just do the processing in a loop, update the status bar and call root.update_idletasks() to allow the GUI to redraw. (Assuming you are using Tkinter.)
If you want the GUI to remain responsive so for example you can have a Cancel button, then I would make a single thread and process all the files in that thread. Don't sleep in the thread; call root.update() to give some time to event handling. Somehow you will have to notify the main thread that the worker thread is done.
The only reason I can think of to make a separate thread for each image is if the process is significantly I/O bound. My guess is that Tiff to PDF conversion is CPU-intensive and a single worker thread will be plenty.
More notes below...
> Here's my method which takes the files in the ListBox and sends them off
> to my Convert() class (self.convert = Convert()).
> <code>
> def convertTiff2PDF(self):
> from time import time
> #Let's see how long this takes... I saw Kent do this on the
> #Python Tutor list before :-)
> start = time()
> #Grab a tuple which contains width & length
> sizes = self.getPaperSize()
> width = sizes[0]
> length = sizes[1]
> #Count the number of files in the ListBox
> fileCount = self.fileListBox.count()
> for index in range(fileCount):
> #Get each filename
> filenames = str(self.fileListBox.text(index))
> #Setup the worker thread and send the filenames in
> worker = WorkerThread(self, filenames)
> #Start threading
> worker.start()
> #Send each file to be converted
> self.convert.tiff2pdf(width, length, filenames)
The above line should be in the thread, not in the main loop - you are spawning threads that do nothing but update the status display - and they will compete for that.
> #We're done, so clear the ListBox
> self.fileListBox.clear()
> #Check the time again
> end = time()
> msg = '%s Files Processed in %0.3f Seconds.' % (fileCount,
> (end-start))
> #Grab the statusBar and insert the message
> statusBar = self.statusBar()
> statusBar.message(msg, 0)
> </code>
>
> And here's what I'm doing in my Thread class:
> <code>
> class WorkerThread(Thread):
> """Thread class."""
> def __init__(self, parent, files):
> Thread.__init__(self)
> self.parent = parent
> self.files = files
>
> def run(self):
> statusBar = self.parent.statusBar()
> msg = 'Processing: %s, please wait.' % (self.files)
> statusBar.message(msg, 100)
> time.sleep(1)
> </code>
>
> Am I doing this threading properly? Is it 'OK' to start multiple threads
> like this (in the for loop)? It's possible that a user could put 'many'
> files into the ListBox, by 'many' I mean 100-200 files.
It's OK to have multiple threads but yours aren't doing any useful work.
I hope this helps get you on track, it's a bit brief.
Kent
>
> Thanks for your help.
>
> Bill
>
>
> _______________________________________________
> Tutor maillist - Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
>
>
More information about the Tutor
mailing list