[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