Threading for a newbie

K

Koncept

Hi. I am fairly new to Python programming and am having some trouble
wrapping my head around threading.

This is a very basic example of what I am trying to do, and would
greatly appreciate having this code hacked to pieces so that I can
learn from you folks with experience.

What I would like to learn from this example is how to use threads to
call on other classes and append/modify results in a list outside of
scope (basically keep track of variables throught the total threading
process and return them somehow afterwards ). I was thinking about
using some sort of global, but I am not sure what the best approach to
this is.

Thanks kindly for any assistance you may be able to offer.

-- code --

import time, random, threading

order = []

class Foo:
def __init__(self, person):
print "\nFoo() recieved %s\n" % person

class Bar(threading.Thread, Foo):
def __init__(self, name):
threading.Thread.__init__(self, name = name)
self.curName = name
def run(self):
global order
sleepTime = random.randrange(1,6)
print "Starting thread for %s in %d seconds" % \
(self.getName(), sleepTime)
time.sleep(sleepTime)
Foo.__init__(self,self.getName())
print "%s's thread has completed" % self.getName()
order.append(self.getName())

def main():
for person in ['Bill','Jane','Steve','Sally','Kim']:
thread = Bar(person)
thread.start()

# How do I print "order" after all the threads are complete?
print "\nThreads were processed in the following order:"
for i, person in enumerate(order): print "%d. %s" % (i+1,person)

if __name__ == "__main__":
main()
 
S

Scott David Daniels

Koncept said:
Hi. I am fairly new to Python programming and am having some trouble
wrapping my head around threading.
Threading sounds simpler than it is.

Here is a classic Pythonic solution related to yours:
What I would like to learn from this example is how to use threads to
call on other classes and append/modify results in a list outside of
scope (basically keep track of variables throught the total threading
process and return them somehow afterwards ). I was thinking about
using some sort of global, but I am not sure what the best approach to
this is.
You generally want to avoid mutation of anything in more than one
thread, and prefer to only share reading between threads. The only
time you can do more than that is when you _know_ the modification
is "atomic" -- there is no chance another thread can "see" a
half-modified value.

One Pythonic way to do this is to talk to a results-gathering thread
through a Queue (which was designed to handle these inter-thread
issues). I'll just hack up your code a bit.

import time, random, threading, Queue
base = time.time() # just to make time printing simpler


class Server(threading.Thread):

def __init__(self, name, source, destination):
threading.Thread.__init__(self, name=name)
self.name = name
self.source = source
self.destination = destination

def run(self):
while True:
command = self.source.get()
if command is None:
break # Told to stop
result = self.compute(command)
self.destination.put(result)
self.destination.put(None)

def compute(self, operation):
sleep = random.uniform(1, 6)
time.sleep(sleep)
return '%s: %s at %s' % (self.name, operation, time.time()
- base)


def main(servers):
starting = time.time()
commands = Queue.Queue() # Things to do go here
results = Queue.Queue() # results of processing comes out here

# Start up servers waiting for input
for n in range(servers):
thread = Server('s%s' % n, commands, results)
thread.start()

# throw in a bunch of work to be done.
for person in ['Bill', 'Jane', 'Steve', 'Sally', 'Kim']:
commands.put(person)

# throw in a stop command for each server.
for n in range(servers):
commands.put(None)

while True:
result = results.get(True, 10.5)
if result is None:
# A server stopped (no more work to do)
servers -= 1 # one fewer server
if 0 == servers: # If no servers left, we're done
return # All servers are done.
else:
# We got a result.
print '%s: %s' % (time.time() - base, result)


if __name__ == "__main__":
main(3)

--Scott David Daniels
(e-mail address removed)
 
K

Koncept

Scott David Daniels said:
You generally want to avoid mutation of anything in more than one
thread, and prefer to only share reading between threads. The only
time you can do more than that is when you _know_ the modification
is "atomic" -- there is no chance another thread can "see" a
half-modified value.
...

Scott. Thanks so much for your reply. Admittedly, It's going to take me
a bit of time to grok what you posted, but I really do appreciate the
help. I was sure that I was going about the the wrong way, and now I
have a new path to follow. It's really nice to have people lend a hand
when others get stumped. I hope to one day be able to contribute here
in a similar manner!

Best.
 

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,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top