0

파이썬에서 포트 스캐닝 프로그램을 작성하는 데는 모든 것이 잘 작동하지만 프로그램을 종료하기 위해 crtl + c 인터럽트 기능을 구현하고 싶지만 주 프로그램을 중지하지만 여전히 실행중인 스레드가 있습니다. ctrl + c 키를 사용하여 프로그램을 완전히 종료하는 방법은 무엇입니까?파이썬에서 키보드 인터럽트를 구현하는 방법

class StatusChecker(threading.Thread): 
    """ 
    The thread that will check HTTP statuses. 
    """ 

    #: The queue of urls 
    url_queue = None 

    #: The queue our results will go into 
    result_queue = None 

    #: An event that tells the thread to stop 
    stopper = None 

    def __init__(self, url_queue, result_queue, stopper): 
     super().__init__() 
     self.url_queue = url_queue 
     self.result_queue = result_queue 
     self.stopper = stopper 

    def run(self): 
     print_lock = threading.Lock() 
     while not self.stopper.is_set(): 
      try: 
       # this will throw queue.Empty immediately if there's 
       # no tasks left 
       to_check = self.url_queue.get_nowait() 
      except queue.Empty: 
       break # empty queue, we're done! 
      else: 
       with print_lock: 
        print(to_check,' ') 
       self.url_queue.task_done() # the the queue we're done 


class SignalHandler: 
    """ 
    The object that will handle signals and stop the worker threads. 
    """ 

    #: The stop event that's shared by this handler and threads. 
    stopper = None 

    #: The pool of worker threads 
    workers = None 

    def __init__(self, stopper, workers): 
     self.stopper = stopper 
     self.workers = workers 

    def __call__(self, signum, frame): 
     """ 
     This will be called by the python signal module 

     https://docs.python.org/3/library/signal.html#signal.signal 
     """ 
     self.stopper.set() 

     for worker in self.workers: 
      worker.join() 

     sys.exit(0) 


if __name__ == '__main__': 
    # all the variables we'll need 
    num_workers = 2 
    stopper = threading.Event() 
    result_queue = queue.Queue() 
    url_queue = queue.Queue() 

    # populate our work queue 
    for i in range(65535): 
     url_queue.put(i) 

    # we need to keep track of the workers but not start them yet 
    workers = [StatusChecker(url_queue, result_queue, stopper) for i in range(num_workers)] 

    # create our signal handler and connect it 
    #handler = SignalHandler(stopper, workers) 
    #signal.signal(signal.SIGINT, handler) 

    # start the threads! 
    for i, worker in enumerate(workers): 
     print('Starting worker {}'.format(i)) 
     worker.daemon = True 
     worker.start() 

    # wait for the queue to empty 
    try: 
     while threading.active_count() > 0: 
      time.sleep(0.1) 
    except: 
     sys.exit(0) 
    while not result_queue.empty(): 
     url, status = result_queue.get_nowait() 
     print('{} - {}'.format(url, status)) 

답변

0

스레드는 주 프로세스와 동일한 메모리 공간을 공유합니다. 따라서 기술적으로 ctrl-c를 주 프로세스에서 수행하면 스레드 메모리를 할당 해제해야합니다. 쓰레드가 쓰는 중간에 있다면 안전하지 않을 수도 있지만 그렇지 않으면 괜찮을 것입니다. 그렇지 않으면 파이썬의 signal 라이브러리를 사용하고 시그널 핸들러를 생성하여 SIGINT를 트랩 할 수 있습니다.