Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change argument value in a running thread in python

How do I change a parameter of a function running in an infinite loop in a thread (python)? I am new to threading and python but this is what I want to do (simplified),

class myThread (threading.Thread):
   def __init__(self, i):
       threading.Thread.__init__(self)

   def run(i):
       self.blink(i)

   def blink(i):   
       if i!=0:
           if i==1:
               speed=0.10
           elif i==2:
               speed=0.20
           elif i==3:
               speed=0.30    

           while(true):
               print("speed\n")

i=3
blinkThread=myThread(i)
blinkThread.start()

while(i!=0):
i=input("Enter 0 to Exit or 1/2/3 to continue\n")
if i!=0:
   blinkThread.run(i)

Now, obviously this code gives errors regarding the run() method. I want to run the function blink() in infinite loop but change the 'i' variable. I also cannot do it without a thread because I have other portions of code which are doing parallel tasks. What can I do? Thanks!

like image 851
ARN Avatar asked Nov 29 '25 11:11

ARN


2 Answers

Best thing to learn first, is to never change variables from different threads. Communicate over queues:

import threading
import queue

def drive(speed_queue):
    speed = 1
    while True:
        try:
            speed = speed_queue.get(timeout=1)
            if speed == 0:
                break
        except queue.Empty:
            pass
        print("speed:", speed)

def main():
    speed_queue = queue.Queue()
    threading.Thread(target=drive, args=(speed_queue,)).start()
    while True:
        speed = int(input("Enter 0 to Exit or 1/2/3 to continue: "))
        speed_queue.put(speed)
        if speed == 0:
            break

main()
like image 193
Daniel Avatar answered Dec 01 '25 01:12

Daniel


Besides a lot of syntax errors, you're approaching the whole process wrong - there is no point in delegating the work from run to another method, but even if there was, the last while would loop infinitely (if it was actually written as while True:) never checking the speed change.

Also, don't use run() method to interface with your thread - it's a special method that gets called when starting the thread, you should handle your own updates separately.

You should also devote some time to learn OOP in Python as that's not how one makes a class.

Here's an example that does what you want, hope it might help you:

import threading
import time


class MyThread (threading.Thread):

    def __init__(self, speed=0.1):
        self._speed_cache = 0
        self.speed = i
        self.lock = threading.RLock()
        super(MyThread, self).__init__()

    def set_speed(self, speed):  # you can use a proper setter if you want
        with self.lock:
            self.speed = speed

    def run(self):
        while True:
            with self.lock:
                if self.speed == 0:
                    print("Speed dropped to 0, exiting...")
                    break
                # just so we don't continually print the speed, print only on change
                if self.speed != self._speed_cache:
                    print("Current speed: {}".format(self.speed))
                    self._speed_cache = self.speed
            time.sleep(0.1)  # let it breathe

try:
    input = raw_input  # add for Python 2.6+ compatibility
except NameError:
    pass

current_speed = 3  # initial speed

blink_thread = MyThread(current_speed)
blink_thread.start()

while current_speed != 0:  # main loop until 0 speed is selected
    time.sleep(0.1)  # wait a little for an update
    current_speed = int(input("Enter 0 to Exit or 1/2/3 to continue\n"))  # add validation?
    blink_thread.set_speed(current_speed)

Also, do note that threading is not executing anything in parallel - it uses GIL to switch between contexts but there are never two threads executing at absolutely the same time. Mutex (lock) in this sense is there just to ensure atomicity of operations, not actual exclusiveness.

If you need something to actually execute in parallel (if you have more than one core, that is), you'll need to use multiprocessing instead.

like image 31
zwer Avatar answered Nov 30 '25 23:11

zwer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!