首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在python中停止运行无限循环的线程?

如何在python中停止运行无限循环的线程?
EN

Stack Overflow用户
提问于 2018-06-09 18:04:10
回答 2查看 3.6K关注 0票数 0

我编写了一个程序,它有一个主线程,它通过对threading.Thread类进行子类化来派生许多其他线程。

每个这样的子线程都运行一个无限的while循环,在循环中我检查一个条件。如果条件为真,我使用time.sleep(1)使线程休眠1秒,如果条件为假,则线程执行一些计算。

程序本身运行良好,我已经实现了我想要做的事情,我唯一剩下的问题是,在我的工作完成后,我似乎无法停止线程。我希望用户能够通过按下一个按钮或像Ctrl+C那样给键盘中断来杀死所有线程。

为此,我尝试使用了signal模块,并在线程的循环中插入了一个条件,当主线程捕获到一个信号时,它会中断循环,但由于某种原因,它不能工作。有人能帮个忙吗?

编辑:这是一些相关的代码片段:

代码语言:javascript
复制
def sighandler(signal,frame):
    BaseThreadClass.stop_flag = True
class BaseThreadClass(threading.Thread):
    stop_flag = False
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self,*args):
        while True:
            if condition:
               time.sleep(1)
            else:
               #do computation and stuff
            if BaseThreadClass.stop_flag:
               #do cleanup
               break
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-10 00:56:14

您的基本方法是有效的,但是您仍然没有发布足够的代码来显示该缺陷。我添加了几行代码使其可运行,并产生了如下结果:

代码语言:javascript
复制
$ python3 test.py
thread alive
main alive
thread alive
main alive
^CSignal caught
main alive
thread alive
main alive
main alive
main alive
^CSignal caught
^CSignal caught
main alive
^Z
[2]+  Stopped                 python3 test.py
$ kill %2

上面演示的问题涉及到信号处理程序告诉所有线程退出,除了主线程,它仍然运行并仍然捕获中断。示例代码段的此变体的完整源代码为:

代码语言:javascript
复制
import threading, signal, time

def sighandler(signal,frame):
    BaseThreadClass.stop_flag = True
    print("Signal caught")

class BaseThreadClass(threading.Thread):
    stop_flag = False
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self,*args):
        while True:
            if True:
               time.sleep(1)
               print("thread alive")
            else:
               #do computation and stuff
               pass
            if BaseThreadClass.stop_flag:
               #do cleanup
               break

signal.signal(signal.SIGINT, sighandler)

t = BaseThreadClass()
t.start()

while True:
    time.sleep(1)
    print("main alive")

这里的问题是主线程从不检查退出条件。但是,由于您从未发布主线程做了什么,也没有发布信号处理程序是如何激活的,或者关于线程是否会在没有检查退出条件的情况下运行很长时间的信息...我还是不知道你的程序出了什么问题。库文档中显示的signal example会引发异常,以便转移主线程。

然而,对于这个任务来说,信号是一个相当低级的概念。我冒失地写了一个更天真的主线版本:

代码语言:javascript
复制
try:
    t = BaseThreadClass()
    t.start()
    while True:
        time.sleep(1)
        print("main alive")
except KeyboardInterrupt:
    BaseThreadClass.stop_flag = True
    t.join()

此版本捕获由默认中断处理程序抛出的异常,向线程发出停止信号,并等待线程停止。将except子句更改为finally甚至可能是合适的,因为我们可能还希望清理线程中的其他错误。

票数 1
EN

Stack Overflow用户

发布于 2018-06-10 00:36:18

如果您想要执行这种“协作”轮询关闭,您可以使用threading.Event来发出信号:

代码语言:javascript
复制
import threading
import time

def proc1():
    while True:
        print("1") # payload
        time.sleep(1)

        # have we been signalled to stop?
        if not ev1.wait(0): break 

    # do any shutdown etc. here
    print ("T1 exiting")

ev1 = threading.Event()
ev1.set()

thread1 = threading.Thread(target=proc1)
thread1.start()

time.sleep(3)

# signal thread1 to stop
ev1.clear()

但请注意,如果“有效负载”执行了诸如网络或文件IO之类的阻塞操作,该操作将不会中断。您可以使用超时来执行这些阻塞操作,但这显然会使您的代码变得复杂。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50773086

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档