[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.

> 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