Multithreading Python—如何实现';可停止';线

Multithreading Python—如何实现';可停止';线,multithreading,python-3.x,class,Multithreading,Python 3.x,Class,发布了一个创建可停止线程的解决方案。然而,我在理解如何实现这个解决方案时遇到了一些问题 使用代码 import threading class StoppableThread(threading.Thread): """Thread class with a stop() method. The thread itself has to check regularly for the stopped() condition.""" def __init__(self)

发布了一个创建可停止线程的解决方案。然而,我在理解如何实现这个解决方案时遇到了一些问题

使用代码

import threading

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self):
        super(StoppableThread, self).__init__()
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()
如何创建一个线程来运行一个函数,该函数每1秒向终端打印一次“Hello”。5秒钟后,我使用.stop()停止循环函数/线程

我再一次在理解如何实现这个停止解决方案时遇到困难,以下是我到目前为止得到的结果

import threading
import time

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self):
        super(StoppableThread, self).__init__()
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()

def funct():
    while not testthread.stopped():
        time.sleep(1)
        print("Hello")

testthread = StoppableThread()
testthread.start()
time.sleep(5)
testthread.stop()
上面的代码创建了线程testthread,可以通过testthread.stop()命令停止该线程。据我所知,这只是创建一个空线程。。。是否有一种方法可以创建一个运行funct()的线程,该线程将在使用.stop()时结束。基本上,我不知道如何实现StoppableThread类以线程的形式运行funct()函数

常规线程函数的示例

import threading
import time

def example():
    x = 0
    while x < 5:
        time.sleep(1)
        print("Hello")
        x = x + 1

t = threading.Thread(target=example)
t.start()
t.join()
#example of a regular threaded function.
导入线程
导入时间
def示例():
x=0
当x<5时:
时间。睡眠(1)
打印(“你好”)
x=x+1
t=线程。线程(目标=示例)
t、 开始()
t、 加入
#常规线程函数的示例。

在原始示例中如何使用代码存在几个问题。首先,您没有向基构造函数传递任何构造函数参数。这是一个问题,因为正如您在纯线程示例中所看到的,构造函数参数通常是必需的。您应该重写
StoppableThread.\uuuu init\uuu
,如下所示:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self._stop_event = threading.Event()
因为您使用的是Python3,所以不需要向
super
提供参数。现在你可以做了

testthread = StoppableThread(target=funct)
这仍然不是最佳解决方案,因为
funct
使用外部变量
testthread
来停止自身。虽然这对于像您这样的一个小例子来说还可以,但使用这样的全局变量通常会导致巨大的维护负担,您不想这样做。更好的解决方案是为您的特定任务扩展通用的
StoppableThread
类,这样您就可以正确地访问
self

class MyTask(StoppableThread):
    def run(self):
        while not self.stopped():
            time.sleep(1)
            print("Hello")

testthread = MyTask()
testthread.start()
time.sleep(5)
testthread.stop()
如果您绝对不想扩展
StoppableThread
,您可以在任务中使用该函数,而不是读取全局变量:

def funct():
    while not current_thread().stopped():
        time.sleep(1)
        print("Hello")

testthread = StoppableThread(target=funct)
testthread.start()
sleep(5)
testthread.stop()

受上述解决方案的启发,我为这个问题创建了一个小库ants

范例

from ants import worker

@worker
def do_stuff():
    ...
    thread code
    ...

do_stuff.start()
...
do_stuff.stop()
在上面的示例中,do_stuff将在一个单独的线程中运行,该线程在
中被调用,而在1:
循环中被调用

您也可以有触发事件,例如,在上面的替换
do_stuff.start()
do_stuff.start(lambda:time.sleep(5))
中,每5秒触发一次


该库非常新,正在GitHub上进行工作

我发现了一些可停止线程的实现-它不依赖于您检查它是否应该继续在线程内运行-它会“注入”一个异常到包装函数中-只要您不执行以下操作,它就会工作:

while True: 
    try: 
        do something
    except:
        pass
绝对值得一看

见:


也许我会用这种机制扩展我的wrapt\u timeout\u decorator,你可以在这里找到:

你需要在线程中做一些事情来响应事件。例如,检查每次迭代后是否停止了
self.stopped
。除非您这样做,否则线程不会神奇地停止运行。您的意思是
而不是testthread.stopped()
?您从未扩展线程或传入要运行的任务。你认为
funct
将如何运行?你能举一个例子,说明如何让一个无法停止的常规线程每秒运行
print('Hello')
行吗?我认为这将帮助你思考这个问题。现在看来,你需要一个基本的线程教程,而不是帮助你深入研究。我为这篇文章删去了很多代码,不小心删掉了.start()。我在文章中添加了一个常规线程函数的示例。基本上,我的问题是如何创建引用funct()函数的StoppableThread类的实例。。。我想在线程中运行funct(),但可以选择使用.stop()命令结束该线程。非常有用!非常感谢你!这是一个有效的解决方案,我会花更多的时间复习你的答案,这样我就可以学习了。非常感谢你@前门。很高兴你成功了。它实际上提出了一个关于线程的问题。我会尽快链接我的帖子,因为我认为这可能是相当相关的你。请做!再次感谢你!受此启发,我创建了一个小小的图书馆,ants。仍在构建中,但您可以在此处找到它
ImportError:无法从“ants”导入名称“worker”(C:\Users\MN\AppData\Local\Programs\Python\Python37\lib\site packages\ants\\uuuu init\uuuuuuuu.py)