[Tutor] While Loop and Threads

James Chapman james at uplinkzero.com
Tue Jul 15 15:14:22 CEST 2014


So if I understand this correctly, you want to start a thread and then stop
it after a certain time period?

Here's an adapted example that includes a timer. (I believe in learning by
example where possible)
With that said, if it were my code going into production I'd move the timer
logic out of the thread and only signal the thread when it should exit.
Keep the logic within the thread simple and try and make each
method/function do one thing only. It makes for testable, reusable code.

In my new example
* The first thread should exit because the time limit is met.
* The second thread should exit because the Event is set.

Hope this helps...

James



import time
import threading

class ThreadExample(object):

    def __init__(self):
        self.thread1Stop = threading.Event()
        self.thread2Stop = threading.Event()
        self.timeFinish = time.time() + 12

    def threadWorkerOne(self, _arg1, _arg2):
        print("THREAD1 - started with args: %s, %s" % (_arg1, _arg2))
        while(not self.thread1Stop.is_set()):
            while(time.time() < self.timeFinish):
                print("THREAD1 - Running")
                if (self.thread1Stop.is_set()):
                    break # Break out of the time while loop
                time.sleep(1)
            if time.time() > self.timeFinish:
                print("THREAD1 - Time limit exceeded")
                self.thread1Stop.set()
        print("THREAD1 - Exiting because thread1Stop is TRUE")

    def threadWorkerTwo(self, _arg1, _arg2):
        print("THREAD2 - started with args: %s, %s" % (_arg1, _arg2))
        while(not self.thread2Stop.is_set()):
            while(time.time() < self.timeFinish):
                print("THREAD2 - Running")
                if (self.thread2Stop.is_set()):
                    break # Break out of the time while loop
                time.sleep(1)
            if time.time() > self.timeFinish:
                print("THREAD2 - Time limit exceeded")
                self.thread2Stop.set()
        print("THREAD2 - Exiting because thread2Stop is TRUE")

    def main(self):
        t1 = threading.Thread(target=self.threadWorkerOne, args = ("arg1",
"arg2"))
        t1.start()
        t2 = threading.Thread(target=self.threadWorkerTwo, args = ("arg1",
"arg2"))
        t2.start()
        print("MAIN - sleep(5)")
        time.sleep(5)
        print("MAIN - setting thread1Stop")
        self.thread1Stop.set()
        print("MAIN - sleep(10)")
        time.sleep(10)
        print("MAIN - exiting...")

if __name__ == '__main__':
    runExample = ThreadExample()
    runExample.main()







--
James


On 15 July 2014 11:09, Oğuzhan Öğreden <oguzhanogreden at gmail.com> wrote:

> Thanks!
>
> I'll have a side question. If I implement this idea to my case,
> threadWorker() would look like this:
>
>
> def threadWorker(_arg1, _arg2):
>     print("Starting worker thread with args: %s, %s" % (_arg1, _arg2))
>     while g_threadStop.is_set() == False:
>         ## here comes a for loop:
>             while time_now < time_finish: # time_finish and counter
> defined somewhere above and
>                 print("Thread running.")      # and expression of the
> condition is intentionally (and necessarily, I believe)
>                 counter += 1                     # left out of for
> expression.
>                 print(counter)
>                 time.sleep(1)
>     print("Thread exiting...")
>
> Of course in this case value of g_threadStop.is_set() is not checked until
> for loop finishes its iteration. Would the suggestion below be a good way
> to handle the event signal?
>
>
> def threadWorker(_arg1, _arg2):
>     print("Starting worker thread with args: %s, %s" % (_arg1, _arg2))
>     ## here comes a for loop:
>         while time_now  < time_finish: # counter and count_until defined
> somewhere above and
>             if g_threadStop.is_set() == False:
>                 # return something or raise an exception to signal
> iteration was interrupted
>             print("Thread running.")   # and expression of the condition
> is intentionally (and necessarily, I believe)
>             counter += 1                  # left out of for expression.
>             time.sleep(1)
>     print("Iteration done.")
>
> This comes with a problem, due to time.sleep(1), signal is handled with a
> delay. I can think of a work around through GTK:
>
>    1. changing (1) to something like while time_now < time_finish -
>    actually that is the way it is in original code.
>    2. dealing with the counter in the GTK main loop since it's main use
>    is for GTK display of the timer.
>
> But let's now follow your advice and leave GTK out for a while and keep
> imagining I want:
>
>    1. Command line output for the timer.
>    2. Event signal handling without a delay.
>
> I have a felling that 'thread-way of thinking' would come up with another
> thread for counter. Is that correct? If yes, would there be an obvious
> advantage to either using GTK main loop or dealing with another thread?
>
> 2014-07-14 20:24 GMT+02:00 James Chapman <james at uplinkzero.com>:
>
> OK, so I mocked up an example now...
>>
>>
>>
>> import time
>> import threading
>>
>> g_threadStop = threading.Event()
>>
>> def threadWorker(_arg1, _arg2):
>>     print("Starting worker thread with args: %s, %s" % (_arg1, _arg2))
>>     while(not g_threadStop.is_set()):
>>         print("Thread running.")
>>         time.sleep(1)
>>     print("Thread exiting...")
>>
>> def main():
>>     t = threading.Thread(target=threadWorker, args = ("arg1", "arg2"))
>>     t.start()
>>     print("Main thread sleeping for 10 seconds...")
>>     time.sleep(5)
>>     print("Main thread setting g_threadStop")
>>     g_threadStop.set()
>>     time.sleep(3)
>>     print("Main thread exiting...")
>>
>> if __name__ == '__main__':
>>     main()
>>
>>
>>
>>
>>
>> --
>> James
>>
>>
>> On 14 July 2014 19:03, James Chapman <james at uplinkzero.com> wrote:
>>
>>> Multi-threading takes practice!
>>>
>>> Are you using an event object to signal the thread should exit? I'm
>>> guessing you're just using a bool which is why it does not work.
>>>
>>> See: https://docs.python.org/3.4/library/threading.html#event-objects
>>>
>>> I'm very short on time and the moment and therefore can't mock up a
>>> working example. If I have time later/tomorrow and you haven't solved it or
>>> no one else has commented I'll try and put something together.
>>>
>>> IMO, move away from GTK until you get threading working as expected,
>>> then add the additional layer. Solve one problem at a time.
>>>
>>> James
>>>
>>> --
>>> James
>>>
>>>
>>> On 13 July 2014 12:23, Oğuzhan Öğreden <oguzhanogreden at gmail.com> wrote:
>>>
>>>> Hi,
>>>>
>>>> I've been practicing with multithreading and gtk for a while and
>>>> recently have observed something I can't quite grasp.
>>>>
>>>> This is basically a timer with a settings window and a countdown window
>>>> which is produced after setting_window passes necessary arguments to thread.
>>>>
>>>> I have a while loop which counts time, inside the thread, while
>>>> variable "runner" is True, which looks like this:
>>>>
>>>>     def run(self):
>>>>         cycle = ['work', 'break', 'long_break']
>>>>         cycle = cycle[:2]*self.workn+cycle[3]
>>>>         self.runner = True
>>>>         sec_count = timedelta(seconds=1)
>>>>
>>>>         while self.runner == True:
>>>>             for i in cycle:
>>>>                 self.setState(i)
>>>>                 print('Start:', i, datetime.now())
>>>>
>>>>                 while self.end_time > datetime.now():
>>>>                     time.sleep(1)
>>>>                     self.duration -= sec_count
>>>>
>>>>                 self.count[self.state] += 1
>>>>
>>>> And I want countdown to stop when countdown_window receives delete
>>>> event, thus I have a countdown_window.stop() function which is defined as
>>>> follows:
>>>>
>>>> def stop(self, *args):
>>>>         pom.count[pom.state] -= 1
>>>>         pom.runner = False # refers to the runner of the thread.
>>>>         print(pom.runner) # prints False,
>>>>         Gtk.main_quit()
>>>>
>>>> What I expect to happen is that while loop to break, but it does not.
>>>>
>>>> Any suggestions?
>>>>
>>>> Best,
>>>> Oğuzhan
>>>>
>>>> _______________________________________________
>>>> Tutor maillist  -  Tutor at python.org
>>>> To unsubscribe or change subscription options:
>>>> https://mail.python.org/mailman/listinfo/tutor
>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20140715/8c96c4c3/attachment.html>


More information about the Tutor mailing list