[Tutor] threading tutorial

Michael C mysecretrobotfactory at gmail.com
Thu Jun 1 11:30:22 EDT 2017


Oh i get it alright, however in my code I have to push the W button like
this:

import pyautogui
import time

pyautogui.keyDown('w')
time.sleep(2)
pyautogui.keyUp('w')

while the example you gave:




 def fn():
   global run_me
   while run_me:
     ... do some work ...

and then elsewhere you go:

 global run_me
 run_me = True
 ... create and start the Thread ...
 ... later ...
 run_me = False
 T.join()





theoretically deals with my problem, in practice though, my function spend
almost
all its time holding down the 'w' button, given how many miliseconds i need
it. and so it's not responsive enough
for this reason.

Is there a way to pause/kill the thread?

thanks!

On Thu, May 25, 2017 at 7:47 PM, Michael C <mysecretrobotfactory at gmail.com>
wrote:

> message received, i ll take a look tomorrow asap.
>
> thanks for replying!!!
>
> On Thu, May 25, 2017 at 3:03 PM, Cameron Simpson <cs at zip.com.au> wrote:
>
>> On 25May2017 11:52, Michael C <mysecretrobotfactory at gmail.com> wrote:
>>
>>> Right now all i need is to grab 3 values from 3 variables before killing
>>> a
>>> thread, like this:
>>>
>>> def stuff():
>>>   do stuff,
>>>    get values, (x,y,d)
>>>
>>> # main code
>>> startthread(stuff(), blah)
>>> # if else need to sleep or kill the thread, and because I'll restart the
>>> thread later, I'd like to get the values from the thread, say x,y,d in
>>> order to restart the thread.
>>> loop.
>>>
>>> Therefore, how do I get a few values from a few variables from the thread
>>> and then close it?
>>>
>>> Threading is very new to me, so I have to be very diligent.
>>>
>>
>> You always need to be diligent with threads :-)
>>
>> Can you explain why you need to use a thread for this? The first cut of
>> your program looks like you could do it with a ordinary function:
>>
>>  def stuff():
>>    ... compute x, y, z ...
>>    return x, y, z
>>
>>  def main():
>>    x, y, z = stuff()
>>
>> OTOH, your later description suggests that you want to kick off a thread
>> to work on something, and have your main program let it run, or pause it.
>> The implication is that x, y, z represent the thread state allowing you to
>> restart it from scratch at the same point where you paused/stopped things.
>>
>> There are a few different ways to manage that scenario. But first, write
>> yourself a small Thread based program to familiarise yourself with threads.
>> For example (untested):
>>
>>  from __future__ import print_function
>>  from time import sleep
>>  from threading import Thread
>>
>>  def thread_main_body():
>>    print("thread started")
>>    for n in range(20):
>>      print("thread", n)
>>      sleep(0.3)
>>    print("thread done")
>>
>>  def main():
>>    print("main")
>>    T = Thread(target=thread_main_body)
>>    print("main: Thread created but _not_ started")
>>    sleep(1)
>>    T.start()
>>    print("thread started")
>>    for n in range(10):
>>      print("main", n)
>>      sleep(0.4)
>>    print("main program waiting for thread")
>>    T.join()
>>    print("main program done")
>>
>> You should see the main thread and your subthread outputs interleaved.
>> The sleeps are just to ensure some interleaving and to give good
>> interactive feel.  It should run for about 8 seconds overall. Make sure
>> you're happy you understand what is happening, why, and when.
>>
>> There are a few things you need to keep in mind with threads (in Python,
>> and to a degree in other languages):
>>
>> 1: You can't kill/stop a Thread. Instead, the usual approach to to share
>> some state with some kind of "running" flag, a boolean saying that the
>> Thread's function should continue. Then the thread polls that regularly.
>> Eg, if the thread function runs a main loop it might look like this:
>>
>>  def fn():
>>    global run_me
>>    while run_me:
>>      ... do some work ...
>>
>> and then elsewhere you go:
>>
>>  global run_me
>>  run_me = True
>>  ... create and start the Thread ...
>>  ... later ...
>>  run_me = False
>>  T.join()
>>
>> so effectively you ask the Thread to stop, and it obeys when it notices
>> the change to "run_me". Using a global for this is pretty crube, and not
>> the general approach, BTW.
>>
>> 2: Like any other function, the local varaibles to the thread function
>> are not available outside. Thus the "global" hack above. So to share state
>> you would usually make some kind of object with the state, and pass it in
>> to the Thread when you create and start it:
>>
>>  def fn(state):
>>    while state.run_me:
>>      ... do stuff, keep important things like results in "state" ...
>>      state.x = 1
>>      state.y = whatever
>>
>>  class State(object):
>>    pass
>>
>>  def main():
>>    state = State()
>>    state.run_me = True
>>    T = Thread(target=fn, args=(state,))
>>    T.start()
>>    for n in range(10):
>>      print("main", n, "x =", state.x, "y =", state.y)
>>      sleep(0.3)
>>    state.run_me = False
>>    T.join()
>>
>> As I remarked, there are a few ways to approach your scenario. The above
>> should get you started on one approach. Pausing can be done in a few ways,
>> either by starting and stopping individual threads, one after another, or
>> by starting one thread and using a mutex of some kind to cause it to
>> suspend activity when needed. Yet another approach is corroutines, but I'd
>> recommend getting threading understood first to avoid confusion.
>>
>> Come back woith some functioning code and more questions.
>>
>> Cheers,
>> Cameron Simpson <cs at zip.com.au>
>>
>
>


More information about the Tutor mailing list