Home > Enterprise >  How do I stop a thread in python which itself is being called inside a loop?
How do I stop a thread in python which itself is being called inside a loop?

Time:10-31

This seems like a particularly confusing question based on the other similar answers I found on SO. I have code similar to the following:

def parentFunction():
    # Other code
    while True:
        var1, var2 = anotherFunction1() # Getting client details after listening on open port
        threading.Thread(target = anotherFunction2, args=(var1, var2)).start()
        childFunction(var1,var2)
        print("PRINT #1: Running in Parent Function") # This only prints once for some reason

def childFunction(var1, var2):
    threading.Timer(10, childFunction, args=(var1,var2)).start()
    print("PRINT #2: Running in child function") # Prints every 10 seconds
    
    # Other code 

    if (someConditionIsMet):
        print("PRINT #3: Exiting") 
        end_process_and_exit_here()

So basically, when I ran the parentFunction(), I would go into a neverending loop where ever 10 seconds, my console would print "PRINT #2: Running in child function". When the someConditionIsMet was true, my console would print "PRINT #3: Exiting" but then it wouldn't exit. Hence, my loop would carry on forever. I am not sure if it's relevant, but parts of the code has a Threading.Lock as well.

Where I have written end_process_and_exit_here() above, I tried using several methods to kill a thread such as

  1. Raising exceptions and setting flags - These assume that I have started my thread outside of my loop so it's not comparable.
  2. Even this qn about looping threads assumes the thread isnt being looped
  3. Killing using join or stop - stop() was not an option I could access. join() was available but it didn't work i.e. after it was called, the next thread (PRINT #2) continued printing.
  4. Other answers suggesting the use of signals (1) (2), also didn't work.
  5. Using sys.exit() or break in different parts of my code also did not result in the threads stopping.

Is there any method for me to easily exit from such a looping thread?

Note: I need to use threading and not multiprocessing.

CodePudding user response:

You could use python-worker, simply add @worker above you function pip install python-worker

from worker import worker

@worker
def anotherFunction2(var1,var2):
   # your code here
   pass

@worker
def parentFunction():
    # Other code
    while True:
        var1, var2 = anotherFunction1() # Getting client details after listening on open port
        function2Worker = anotherFunction2(var1,var2) # this will automatically run as thread since you put @worker above your function
        childFunction(var1,var2)
        print("PRINT #1: Running in Parent Function") # This only prints once for some reason

def childFunction(var1, var2):
    parentWorker = parentFunction(var1, var2)
    
    # Other code 

    if (someConditionIsMet):
        parentWorker.abort()

CodePudding user response:

I'm not certain if this is a bad practice (in fact I feel it may be based on the answers linked in the question saying that we should never 'kill a thread'). I'm sure there are reasons why this is not good and I'd appreciate anyone telling me why. However, the solution that ultimately worked for me was to use .cancel().

So first change would be to assign your thread Timer to a variable instead of calling it directly. So instead of threading.Timer(10, childFunction, args=(var1,var2)).start(), it should be

t = threading.Timer(10, childFunction, args=(var1,var2))
t.start()

Following that, instead of end_process_and_exit_here(), you should use t.cancel(). This seems to work and stops all threads mid-process. However, the bad thing is that it doesn't seem to carry on with other parts of the program.

  • Related