Python,停止线程

Python,停止线程,python,multithreading,kill,Python,Multithreading,Kill,我正在尝试创建一个类,它ping一个ip地址并记录连接/未连接的时间 因为这个类是GUI的一部分,所以当用户要求时,我希望停止这个线程 发现一些Q&A对这个问题进行了重新分级,但都没有导致线程停止 我正在尝试创建一个方法,这个类的一部分将停止self.run() 这是我的Pinger课程: class Pinger(threading.Thread): def __init__(self, address='', rate=1): threading.Thread.__i

我正在尝试创建一个类,它ping一个ip地址并记录连接/未连接的时间

因为这个类是GUI的一部分,所以当用户要求时,我希望停止这个线程

发现一些Q&A对这个问题进行了重新分级,但都没有导致线程停止

我正在尝试创建一个方法,这个类的一部分将停止
self.run()

这是我的
Pinger
课程:

class Pinger(threading.Thread):
    def __init__(self, address='', rate=1):
        threading.Thread.__init__(self)

        self.address = address
        self.ping_rate = rate
        self.ping_vector, self.last_ping = [], -1
        self.start_time, self.last_status = datetime.datetime.now(), []
        self.timestamp, self.time_vector = 0, [datetime.timedelta(0)] * 4

    def run(self):
            self.start_ping()

    def start_ping(self):
        self.timestamp = datetime.datetime.now()
        while True:
            ping_result = os.system('ping %s -n 1 >Null' % self.address)
            self.ping_vector.append(ping_result)

            if self.last_ping != ping_result:
                text = ['Reachable', 'Lost']
                print(str(self.timestamp)[:-4], self.address, text[ping_result])

            round_time_qouta = datetime.datetime.now() - self.timestamp
            self.timestamp = datetime.datetime.now()
            self.update_time_counter(ping_result, round_time_qouta)

            self.last_ping = ping_result
            time.sleep(self.ping_rate)

    def update_time_counter(self, ping_result=0, time_quota=datetime.timedelta(0)):
        """self.time_vector = [[cons.succ ping time],[cons.not_succ ping time],
        [max accum succ ping time],[max accum not_succ ping time] """

        p_vec = [0, 1]

        self.time_vector[p_vec[ping_result]] += time_quota
        if self.time_vector[p_vec[ping_result]].total_seconds() > self.time_vector[
            p_vec[ping_result] + 2].total_seconds():
            self.time_vector[p_vec[ping_result] + 2] = self.time_vector[p_vec[ping_result]]

        self.time_vector[p_vec[ping_result - 1]] = datetime.timedelta(0)

        self.last_status = [ping_result, self.chop_milisecond(self.time_vector[ping_result]),
                            self.chop_milisecond(self.time_vector[ping_result + 2]),
                            self.chop_milisecond(datetime.datetime.now() - self.start_time)]

        print(str(self.timestamp)[:-4], "State: " + ['Received', 'Lost'][ping_result],
              " Duration: " + self.last_status[1], " Max Duration: " + self.last_status[2],
              "Total time: " + self.last_status[3])

    def chop_milisecond(self, time):
        return str(time).split('.')[0]
使用_Thread_stop():


MyPinger.\u Thread\u stop()

我会对您的类进行稍微不同的编码,以作为守护进程运行

保留起始代码,然后使用下一个代码:

MyPinger = threading.Thread(target = self.start_ping, name="Pinger")
MyPinger.setDaemon(True)
MyPinger.start() # launch start_ping
可能会使用_Thread_stop()来阻止它,这有点野蛮…:

if MyPinger.IsAlive():
   MyPinger._Thread__stop() 

正如我在评论中所说的,最简单的方法是在线程应该退出时发出信号。这样,您可以公开事件并让其他线程设置它,同时您可以从线程中检查其状态并根据请求退出

在您的情况下,它可以简单到:

class Pinger(threading.Thread):

    def __init__(self, address='', rate=1):
        threading.Thread.__init__(self)
        self.kill = threading.Event()
        # the rest of your setup...

    # etc.

    def start_ping(self):
        self.timestamp = datetime.datetime.now()
        while not self.kill.is_set():
            # do your pinging stuff

    # etc.

然后,每当您想要停止线程时(比如从您的UI),只要调用它:
pinger\u instance.kill.set()
,就完成了。记住,tho,由于阻塞
os.system()
调用和
time.sleep()
您在
Pinger.start_ping()
方法结束时的
time.sleep()
调用,它需要一段时间才能被杀死。

感谢@zwer提供的线索。 这是我的完整代码(已标记更改)

类Pinger(threading.Thread):
定义初始化(self,地址='',速率=1):
threading.Thread.\uuuuu init\uuuuuu(自)
self.address=地址
自评利率=利率
self.ping\u向量,self.last\u ping=[],-1
self.start\u time,self.last\u status=datetime.datetime.now(),[]
self.timestamp,self.time_vector=0,[datetime.timedelta(0)]*4

self.event=threading.event()#用于在线程应该退出时发出信号,然后定期检查线程是否设置了事件,如果设置了事件则退出。@zwer您可以在代码中进行解释吗?为什么不用事件
wait
替换
while
循环以减少CPU延迟?
class Pinger(threading.Thread):
    def __init__(self, address='', rate=1):
        threading.Thread.__init__(self)

        self.address = address
        self.ping_rate = rate
        self.ping_vector, self.last_ping = [], -1
        self.start_time, self.last_status = datetime.datetime.now(), []
        self.timestamp, self.time_vector = 0, [datetime.timedelta(0)] * 4
        self.event = threading.Event() # <---- Added

    def run(self):
        while not self.event.is_set(): # <---- Added
            self.start_ping()
            self.event.wait(self.ping_rate) # <---- Added ( Time to repeat moved in here )

    def stop(self):       # <---- Added ( ease of use )
        self.event.set()  # <---- Added ( set to False and causes to stop )


    def start_ping(self):
        self.timestamp = datetime.datetime.now()
        # While loop ##--- > Deleted. now it loops in run method #####
        ping_result = os.system('ping %s -n 1 >Null' % self.address)
        self.ping_vector.append(ping_result)

        if self.last_ping != ping_result:
            text = ['Reachable', 'Lost']
            print(str(self.timestamp)[:-4], self.address, text[ping_result])

        round_time_qouta = datetime.datetime.now() - self.timestamp
        self.timestamp = datetime.datetime.now()
        self.update_time_counter(ping_result, round_time_qouta)

        self.last_ping = ping_result
        #### time.sleep (self.ping_rate)  # <---- deleted 

    def update_time_counter(self, ping_result=0, time_quota=datetime.timedelta(0)):
        """self.time_vector = [[cons.succ ping time],[cons.not_succ ping time],
        [max accum succ ping time],[max accum not_succ ping time] """

        p_vec = [0, 1]

        self.time_vector[p_vec[ping_result]] += time_quota
        if self.time_vector[p_vec[ping_result]].total_seconds() > self.time_vector[
            p_vec[ping_result] + 2].total_seconds():
            self.time_vector[p_vec[ping_result] + 2] = self.time_vector[p_vec[ping_result]]

        self.time_vector[p_vec[ping_result - 1]] = datetime.timedelta(0)

        self.last_status = [ping_result, self.chop_milisecond(self.time_vector[ping_result]),
                            self.chop_milisecond(self.time_vector[ping_result + 2]),
                            self.chop_milisecond(datetime.datetime.now() - self.start_time)]

        print(str(self.timestamp)[:-4], "State: " + ['Received', 'Lost'][ping_result],
              " Duration: " + self.last_status[1], " Max Duration: " + self.last_status[2],
              "Total time: " + self.last_status[3])

    def chop_milisecond(self, time):
        return str(time).split('.')[0]

    def get_status(self):
        return self.last_status


c = Pinger('127.0.0.1', 5)
c.start()
time.sleep(10)
c.stop()