如何停止 python 中的线程,该线程本身在循环内被调用?

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

根据我在 SO 上找到的其他类似答案,这似乎是一个特别令人困惑的问题。我有类似于以下的代码:

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()

所以基本上,当我 运行 parentFunction() 时,我会进入一个永无止境的循环,每 10 秒,我的控制台就会打印 "PRINT #2: 运行 在子函数中。当 someConditionIsMet 为真时,我的控制台将打印 "PRINT #3: Exiting" 但随后它不会退出。因此,我的循环将永远进行下去。我不确定它是否相关,但部分代码也有 Threading.Lock。

我在上面写了 end_process_and_exit_here() 的地方,我尝试使用几种方法来杀死一个线程,例如

  1. Raising exceptions and setting flags - 这些假设我已经在我的循环之外启动了我的线程,所以它没有可比性。
  2. Even this qn about looping threads assumes the thread isnt being looped
  3. Killing using join or stop - stop() 不是我可以访问的选项。 join() 可用但没有工作,即调用后,下一个线程 (PRINT #2) 继续打印。
  4. 建议使用 (2) 的其他答案也没有用。
  5. 在我的代码的不同部分使用 sys.exit() 或中断也没有导致线程停止。

有什么方法可以让我轻松退出这样的循环线程吗?

注意:我需要使用线程而不是多处理。

作为更新,我已经设法解决了这个问题。我提出的另一个答案(如下所示)的问题是 .cancel() 本身似乎只适用于一个计时器线程。但是从问题中可以看出,childFunction()本身调用了childFunction(),也可以被parentFunction调用,也就是说可能有多个定时器线程。

对我的具体案例有用的是如下命名我的线程:

t1 = threading.Timer(10, childFunction, args=(var1,var2,number))
t1.name = t1.name + "_timer" + str(number)
t1.start()

此后,我可以通过以下方式取消从此进程创建的所有计时器线程:

for timerthread in threading.enumerate():
    if timerthread.name.endswith('timer' + str(number)):
        timerthread.cancel()

下面是我使用的原始方法,该方法引起了很多问题

我不确定这是否是一种不好的做法(事实上,我觉得这可能是基于问题中链接的答案,即我们永远不应该 'kill a thread')。我敢肯定这是有原因的,我很感激有人告诉我原因。但是,最终对我有用的解决方案是使用 .cancel().

因此,第一个更改是将您的线程定时器分配给一个变量,而不是直接调用它。所以不是threading.Timer(10, childFunction, args=(var1,var2)).start(),而是

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

之后,您应该使用 t.cancel() 而不是 end_process_and_exit_here()。这似乎有效并在进程中停止所有线程。然而,不好的是,它似乎并没有与程序的其他部分一起进行。

您可以使用python-worker,只需在您的函数上方添加@worker 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()