Python Threading loop
Question: I am have problem with this THREDING example. I have it working pretty good,
but my problem is after it shows all 100 student threads. I am trying to put
20 random students in five different classes, but no matter what I do I can't
seem to get the loop to work. If someone could please give me any direction on
this, I would greatly appreciate it.

    
    
    import random, time
    from threading import Thread
    
    
    class Students(Thread):
        ''' Represents a sleepy thread.'''
    
    
        def __init__(self, number, sleepMax):
            ''' Creates a thread with a given Name
            and a random sleep interval less than the maximum. '''
            Thread.__init__(self, name = "Student " + str(number))
            self._RequestInterval = random.randint(1, sleepMax)
    
        def run(self):
            '''Prints the thread's name and sleep interval and sleep
            for that interval. Print the name again at wake-up. '''
            count = 1
            course = 1
            print(" %s, Awaiting Request: %d seconds" % \
                  ( self.getName(), self._RequestInterval))
            time.sleep(self._RequestInterval)
            if count == 20:
                print("%s Has A Spot Obtained in Class" % self.getName(), + course)
                print("Class", course, "has reached it limit!")
                count += 1
                course =+ 1
            else:
                #print("Class ", course, " is full.")
                print("%s Has A Spot Obtained in Class" % self.getName(), + course)
    
    
    
    def main():
        ''' Creates the user's number of threads with sleep
        interval less than the user's maximum. Then start
        the threads'''
    
        NumberOfStudents = 100
        RequestTimer = 5    
        threadList = []
        for count2 in range(NumberOfStudents):
            threadList.append(Students(count2 + 1, RequestTimer))
        for thread in threadList: thread.start()
    
    
    
    main() 
    

I have even tried running my variable outside the class, but crashes.


Answer: There are several problems with this.

  1. The `count` and `course` variables are only in the `run` function, so they are local to that function only. This means that threads are not sharing this information. The solution: move them outside so that they are _class_ variables (that is, they are now `Students.count` and `Students.course`).
  2. Your print statements are a bit messed up. Using `print(a,b,c,...)` will print each of `a,b,c,...` on a separate line. The solution, enclose the thread's name and course number in a tuple and modify the format string slightly.
  3. `course =+ 1` would've set `course` to `1` (because it's the same thing as `course = +1`) had that part of the if statement ever been executed (which it wasn't because of problem #1). Solution: flip the `=+` so that it's `course += 1`.
  4. `count += 1` only happens when `count` is 20. You want this in the **else** part of the if statement. Also, in the **then** part, add the the line `count = 0` to reset the count.
  5. Because these threads are running asynchronously, it can and does happen that `count` will go from 19 to 21 before you check `if count == 20`. Fixing this requires somewhat more advanced thread handling.

Below is the code with each of these problems fixed, except the last one
(where I changed `count == 20` to `count >= 20` to at least show something
interesting happen).

    
    
    import random, time
    from threading import Thread
    
    
    class Students(Thread):
        ''' Represents a sleepy thread.'''
        count = 1
        course = 1
    
        def __init__(self, number, sleepMax):
            ''' Creates a thread with a given Name
            and a random sleep interval less than the maximum. '''
            Thread.__init__(self, name = "Student " + str(number))
            self._RequestInterval = random.randint(1, sleepMax)
    
        def run(self):
            '''Prints the thread's name and sleep interval and sleep
            for that interval. Print the name again at wake-up. '''
            print(" %s, Awaiting Request: %d seconds" % \
                  ( self.getName(), self._RequestInterval))
            time.sleep(self._RequestInterval)
            if Students.count >= 20:
                print("%s Has A Spot Obtained in Class %s" % (self.getName(), Students.course))
                print("Class", Students.course, "has reached it limit!")
                Students.course += 1
                Students.count = 0
            else:
                #print("Class ", course, " is full.")
                print("%s Has A Spot Obtained in Class %s" % (self.getName(), Students.course))
                Students.count += 1
    
    
    
    def main():
        ''' Creates the user's number of threads with sleep
        interval less than the user's maximum. Then start
        the threads'''
    
        NumberOfStudents = 100
        RequestTimer = 5    
        threadList = []
        for count2 in range(NumberOfStudents):
            threadList.append(Students(count2 + 1, RequestTimer))
        for thread in threadList: thread.start()
    
    
    
    main() 
    

