2017-12-07 1 views
1

IP 주소를 핑 (ping)하고 연결된/연결되지 않은 시간에 대한 레코드를 유지하는 클래스를 만들려고합니다.Python, 스레드 중지

이 클래스는 GUI의 일부이므로 사용자가 물어볼 때이 스레드를 중지하고 싶습니다.

발견 된 일부 Q &이 문제를 해결했지만 어느 것도 실제로 스레드를 중지시키지 않습니다.

나는 방법, 여기 내 Pinger 클래스의 self.run()

중지됩니다이 클래스의 일부를 만들려고 노력 해요 :

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] 
+1

사용 ['threading.Event'] (https://docs.python.org/2/library/threading.html#event-objects) 신호에의하여 스레드가 종료해야하는 경우 스레드를 설정하고 이벤트가 설정된 경우 스레드에서 주기적으로 검사를 수행 한 다음 종료하십시오. – zwer

+1

@zwer 코드로 설명 할 수 있습니까? –

답변

1

내가 말한대로 내 의견에 가장 쉬운 방법은 threading.Event을 사용하여 종료해야 할 때 스레드에 신호를 보내는 것입니다. 그렇게하면 이벤트를 노출 할 수 있고 다른 스레드가 스레드 내에서 상태를 확인하고 요청시 종료 할 수 있도록 설정할 수 있습니다. pinger_instance.kill.set()를하고 완료 : 그냥에 전화, 당신이 원하는 때마다 다음 스레드가 (당신의 UI에서처럼) 중단

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. 

: 귀하의 경우

,처럼 간단 할 수있다. 계속 os.system() 콜을 차단하고 time.sleep()으로 인해 Pinger.start_ping() 메소드가 종료되어 죽기까지 시간이 걸릴 수 있음을 명심하십시오.

0

사용 _Thread_stop() :

MyPinger._Thread__stop을()

1

데몬으로 실행하려면 클래스를 조금 다르게 코딩해야합니다.

휴가 start_ping 코드 출력 및 다음 코드를 사용합니다

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

@zwer에게 감사드립니다. 여기 (변경 사항이 표시됩니다) 내 전체 코드

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